質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

2回答

1251閲覧

入力項目の多い画面の設計について

annderber

総合スコア98

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

2グッド

2クリップ

投稿2017/12/14 16:25

編集2017/12/16 05:02

お世話になります。

現在作成している入力フォームで、かなりネストの深いものがあります。具体的に言うと、一対多の関係にあるフォーム群が2つあり、これがツリー構造のように下に伸びています。

またこのフォームはJavaScriptで動的に増やせるようにしています。
ここで問題なのがname属性のつけ方です。動的に増えるフォーム内にチェックボタンラジオボタンが複数あるため、フォームを追加する際にJavaScriptでname属性の[]内の値をインクリメントしています。
これが非常に厄介で例えばname="hoge[0][huga][1][]のようなフォームが沢山あります。

このように一対多の関係にあるフォームが複数ある場合の画面をどう作成したらいいでしょうか。なるべく1つの画面に収まるようにしたいです。

ここでの1つの画面とは画面遷移せず、またメインの入力画面にすぐ戻れるようになっている状態という意味でとらえていただければと思います。なので、フォームを分割してモーダルなどで表示したりタブで分けたりするのもいいかなと思います。

改善したい点は2つで。
・長いname属性
・画面の表示領域にフォームが詰まりすぎてデザインがよろしくない
になります。

画面レイアウトイメージは以下のような感じです。
イメージ説明

質問が分かりづらくてすいません。
よろしくお願いします。

追記:
javascript側でのフォーム追加処理はこんな感じです。※jquery使ってます

javascript

1$load_content.on("click",".js_add_form_child", function() { 2 //一番最後のフォームグループ取得 3 var $form_group = $(this).parents('.panel-body').find(".form_group").last(); 4     //フォームグループの要素数からname属性インクリメント用の値取得 5 var new_form_cnt = $(this).parents('.panel-body').find(".form_group").length; 6 7 //既存のフォームのname属性から新しいフォームの用のname属性文字列を生成 8 var new_form1_name = $form_group.find(".js_form1").attr("name").replace(/(table_name[\d+][form1][)\d+(])/g, "$1"+new_form_cnt+"$2"); 9 var new_form2_name = $form_group.find(".js_form2").attr("name").replace(/(table_name[\d+][form2][)\d+(])/g, "$1"+new_form_cnt+"$2"); 10 var new_form3_name = $form_group.find(".js_form3").attr("name").replace(/(table_name[\d+][form3][)\d+(])/g, "$1"+new_form_cnt+"$2"); 11 12 //既存のフォームをクローンしてフォーム群の末尾に追加 13 $form_group.clone(false) 14 .find(".js_form1").attr('name', new_form1_name).end() 15 .find(".js_form2").attr('name', new_form2_name).end() 16 .find(".js_form3").attr('name', new_form3_name).end() 17 .insertAfter($form_group); 18 });

new_formのname属性生成処理は正規表現の使い方で1つにまとめられると思ってます

matobaa, LLman👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takito

2017/12/15 00:20

画面のレイアウトイメージを出していただけると何かよいアイデアが出せるかもしれませんが可能ですか?
annderber

2017/12/15 00:37

コメントありがとうございます。追加いたします。
退会済みユーザー

退会済みユーザー

2017/12/15 01:56

繰り返し項目は同じ仕様ならまとめることは可能ですが、提出先に問合せしましょう。(上限まで書くか)
m.ts10806

2017/12/15 02:20 編集

「1つの画面」という表現には色々と含まれると思います。ブラウザは横にも縦にもスクロール可能なので、スクロールすれば「1つの画面」は無限の幅を持ちます。「最大化した状態で全て見える」とするのであれば、「JavaScriptで動的に増やせる」時点で制限は不可能です。「複数ページに渡らず」という捉え方もできますので、(ブラウザを縦横小さく畳むこともできますし)「1つの画面」というものの定義をしっかり提示された方がより欲しい情報・回答が得られるかと思います。
annderber

2017/12/15 02:38

コメントありがとうございます。再度修正しました。
guest

回答2

0

なるべく1つの画面に収まるようにしたいです。

この要望がmustかどうかではないでしょうか。

mustであるなら、ある程度処理が複雑になることはあきらめるしかないでしょう。

そうでなく手順の分割が可能であるなら、
1)基本情報の入力
2)フォーム群1の入力
3)フォーム群2の入力
・・・
というように画面を分けた方がよいと思います。

画面遷移なしに1画面で完結できる利点は、全ての入力内容を確認しながら作業できることと、データのカタチとして完全な状態でDBに格納できる点などがあげられます。
その点、手順を分割した場合は一度不完全な状態で保存しなければなりません。

誰かがそれを見て何らかの不都合が生じるのであれば、不完全な状態の保存をしてはいけない=手順分割できない、ということになります。

逆の見方をすれば、手順が分割されている方が部分的な保存が可能であり、誤った操作をしても今作業している画面の情報が失われるだけで、全てが消えてしまうことはありません。

画面遷移なしの場合は、入力が完全に終わるまで席を離れられないうえ、誤操作などで「せっかく入力したものが全て水の泡・・・」みたいなことも想定されます。

私としては「入力画面」の滞在時間はできるかぎり短くすべきと思います。

ただし、例えばその入力画面が「手動編集用」であって別ルートでデータ入力される仕組みがあるのであれば、入力項目の多い編集画面もアリだと思います。

あまり具体的な解決方法は提示できませんでしたが、以上ご参考まで。

投稿2017/12/15 06:34

takito

総合スコア3111

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

annderber

2017/12/15 09:13

コメントありがとうございます。 できれば私も画面分割をしたいと考えていますが、 一覧性が高い方が好まれる場合もあるようです。 最近だとajaxでフォーム毎にデータを更新するところも多い気がします。
think49

2017/12/15 14:15 編集

誤コメントの為、削除
guest

0

ベストアンサー

多次元配列

これが非常に厄介で例えばname="hoge[0][huga][1][]のようなフォームが沢山あります。

逆に質問させて頂きたいのですが、なぜそんなに複雑な名前が必要なのでしょうか。
JavaScriptで動的に要素を増やす場合に配列構造が必要になるのは分かります。
が、formはネストできず、formと各要素の関係性も一対多なので、要素の名前も一次元配にしかなり得ないと考えています。
フォーム群1に対して、フォーム群1-1,1-2が増えて行くのなら、

HTML

1<fieldset> 2 <legend>フォーム群1-1</legend> 3 <input name="foo-1[0]"> 4 <input name="foo-1[1]"> 5</fieldset> 6 7<fieldset> 8 <legend>フォーム群1-2</legend> 9 <input name="foo-2[0]"> 10 <input name="foo-2[1]"> 11</fieldset>

サーバサイドで多次元配列を受け取れるなら、

HTML

1<fieldset> 2 <legend>フォーム群1-1</legend> 3 <input name="foo[0][0]"> 4 <input name="foo[0][1]"> 5</fieldset> 6 7<fieldset> 8 <legend>フォーム群1-2</legend> 9 <input name="foo[1][0]"> 10 <input name="foo[1][1]"> 11</fieldset>

index値が多少増える程度で名前はそこまで長くはならないように思います。

JavaScriptコード

javascript側でのフォーム追加処理はこんな感じです。※jquery使ってます

HTMLが見えないのでどういう理屈でそのコードに至ったのかまで読み取れませんでしたが、私なら次のように書きます。

HTML

1<form> 2 <input class="insert-fieldset" type="button" value="追加"> 3 <fieldset> 4 <legend>フォーム群1</legend> 5 <p><input type="text" name="table[0][text][0]"></p> 6 <p><input type="text" name="table[0][text][1]"></p> 7 8 <input class="insert-fieldset" type="button" value="追加"> 9 10 <fieldset> 11 <legend>フォーム群1-1</legend> 12 <p><input type="text" name="table[0][group][0][0]"></p> 13 <p><input type="text" name="table[0][group][0][1]"></p> 14 </fieldset> 15 16 <fieldset> 17 <legend>フォーム群1-2</legend> 18 <p><input type="text" name="table[0][group][1][0]"></p> 19 <p><input type="text" name="table[0][group][1][1]"></p> 20 </fieldset> 21 </fieldset> 22 23 <fieldset> 24 <legend>フォーム群2</legend> 25 <p><input type="text" name="table[1][text][0]"></p> 26 <p><input type="text" name="table[1][text][1]"></p> 27 28 <input class="insert-fieldset" type="button" value="追加"> 29 30 <fieldset> 31 <legend>フォーム群2-1</legend> 32 <p><input type="text" name="table[1][group][0][0]"></p> 33 <p><input type="text" name="table[1][group][0][1]"></p> 34 </fieldset> 35 36 <fieldset> 37 <legend>フォーム群2-2</legend> 38 <p><input type="text" name="table[1][group][1][0]"></p> 39 <p><input type="text" name="table[1][group][1][1]"></p> 40 </fieldset> 41 </fieldset> 42</form> 43 44<script> 45'use strict'; 46jQuery('form').on('click', '.insert-fieldset', function handleClick (event) { 47 var input = jQuery(event.target), 48 nestLevel = input.parents('fieldset').length + 1, 49 lastFieldset = input.nextAll('fieldset:last()'), 50 fieldset = lastFieldset.clone(true), 51 legend = fieldset.find('legend'), 52 textNode = legend[0].firstChild, 53 beforeTopLevelCaption = textNode.data, 54 match = /^(\D*(?:\d+\D*)*)(\d+)$/.exec(beforeTopLevelCaption), 55 afterTopLevelCaption = match[1] + ++match[2]; 56 57 textNode.data = afterTopLevelCaption; 58 59 for (var i = 1, len = legend.length, text, index; i < len; ++i) { 60 textNode = legend[i].firstChild; 61 text = textNode.data; 62 index = text.indexOf(beforeTopLevelCaption); 63 64 if (index !== -1) { 65 textNode.data = text.slice(0, index) + afterTopLevelCaption + text.slice(index + afterTopLevelCaption.length); 66 } 67 } 68 69 for (var i = 0, inputList = fieldset.find('input[type="text"]'), len = inputList.length, input, name, reg = /[\d+(?=])/g, result, j, index, bracket; i < len; ++i) { 70 input = inputList[i]; 71 name = input.name; 72 j = 0; 73 reg.lastIndex = 0; 74 75 while (result = reg.exec(name), ++j < nestLevel); 76 77 index = result.index; 78 bracket = result[0]; 79 input.name = name.slice(0, index) + '[' + (+bracket.slice(1) + 1) + ']' + name.slice(index + bracket.length + 1); 80 } 81 82 lastFieldset.after(fieldset); 83}); 84</script>

Re: annderberさん

投稿2017/12/15 03:41

編集2017/12/18 05:54
think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

annderber

2017/12/15 09:10

コメントありがとうございます。 私の場合サーバーサイドで処理を行いやすくするためにname属性が長くなりがちです。 私的命名規則では以下になります。 name="table_name[form_gruop1_index][form_name][form_group2_index]" checkboxの場合は複数の値を受け取ることを想定し、末尾に[]を増やします。 name="table_name[form_gruop1_index][form_name][form_group2_index][]" 先頭にテーブル名を付けるのはサーバー側でテーブル毎の値をまとめて取得できるようにするためです。 ここは本来必要ないので省略してもいいですね。 think49さんの回答を見て、以下の方がいい気がしてきました。  name="table_name[form_gruop1_index][form_group2_index]form_name"
think49

2017/12/15 14:13

フォーム1、フォーム2を含めて、「一つの多次元配列」にまとめるのが目的でしょうか。 その場合は name="table[0][name][0][0]" になるのは致し方ないように思います。 多次元配列部分を短くしたいのなら、多次元配列を使う事を諦めるしかありませんが、管理性を求めて多次元配列を使っていると思われる為、名前を短くするために多次元配列を廃止するのは、本末転倒だと私は思います。
annderber

2017/12/16 03:16

コメントありがとうございます。 まさに1つの多次元配列にまとめるのが目的です。 やはりあきらめるしかないでしょうか。また面倒なのが、html側のname属性を変更するとjavascript側でname属性の値をインクリメントする処理部分も修正する必要があるというところです。正規表現をうまく使えば回避できそうですが。
think49

2017/12/16 03:47

> javascript側でname属性の値をインクリメントする処理部分も修正する必要がある 末尾のインデックス値をインクリメントするなら、ご想像の通り、正規表現で対応できますね。 最も、サーバサイドにPHPを使用しているのなら、name="foo[]" で良い気もします(インデックス値はPHPが補完します)。 一元管理出来るのなら、基本的にはコード量が減ります。 が、annderber さんはむしろ負担に感じているようなので、何かしらコードの書き方に問題がありそうです。 例えば、JavaScriptでノードを動的に追加する関数は一つだけ定義すれば良いのですが、そうなっているでしょうか。 [追加] ボタンのdata-targer属性に「対象のノードを特定するセレクタ文字列を指定する」や「[追加] ボタンの兄弟要素を元にノードを挿入する」という方法が考えられます。
annderber

2017/12/16 05:06

コメントありがとうございます。 javasciprt側でのフォーム生成処理のコードを質問項目に追加しました。 そこまで悪い処理でないと思っているのですが、どうでしょう。 また動的にフォームを追加する場合だとまず初期表示でphp側でforeachなどでname属性にindexを渡してやって、その後の動的追加処理はjavascirptでやるという処理が2つに分けられているという感じがあまり好きでないですね。面倒くさがりすぎなのかもしれないですが。
think49

2017/12/18 05:54

> javasciprt側でのフォーム生成処理のコードを質問項目に追加しました。 親記事に追記しました。
annderber

2017/12/20 12:52

コメントありがとうございます。 返信おくれてすみません。 わざわざコードのサンプルまで書いていただけるとは! 現在コードを読んでいますが、私にとっては結構複雑なコードで読むのに手間取っていますw 少しずつ読み解いて勉強させていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問