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

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

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

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

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

2回答

1805閲覧

連動するプルダウンメニューと行の追加の併用(HTML,Javascript)

safari13872021

総合スコア0

HTML5

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

JavaScript

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2021/02/22 10:06

前提・実現したいこと

①1行に2つのプルダウンメニュー表示させる。
②プルダウンメニューは1つの目の選択に応じて、2つ目の選択しが連動する。
③行数は動的で「ボタンを押す」ことで増減する。

上記のような一覧表をhtmlとjavascriptで作成したいと考えております。

発生している問題・エラーメッセージ

②プルダウンメニューの連動と③行数の増減
それぞれを実装することはできたのですが、それぞれを両立させようとすると上手くいきません。

エラーメッセージ
ロジック判定が行えるようなエディターを使用できないため、エラーは確認できておりません。
おそらく行の追加時に1行目の要素だけに連動しているようなので、
変数の定義の仕方に問題があるのではないかと考えております。

該当のソースコード

<title>sample</title> <meta charset="UTF-8"> </head> <table border="1" cellspacing="2" cellpadding="2"> <tr> <th class="SeiTH">No.</th> <th class="SeiTH">追加/削除</th> <th class="SeiTH" nowrap align="left">選択肢1</th> <th class="SeiTH" nowrap align="left">選択肢2</th> </tr> <tbody id="list_main" > <tr> <td class="%tdclass%">%no%</td> <td class="%tdclass%"> <input type="button" value="+" onclick="addList(this);" /> <input type="button" value="-" onclick="removeList(this);" /> </td> <td class="%tdclass%"> <select name="ah_keihi" id="ah_keihi" onchange="resetValue();changeCategory()">%Y0003% <option value="0">≪選択してください≫</option> <option value="1">近郊交通費</option> <option value="2">出張旅費</option> <option value="3">その他</option> </select> </td> <td class="%tdclass%"> <select name="sh_keihi" id="sh_keihi">%Y0004% <option value="0">≪選択してください≫</option></select> </td> </table> <script language="JavaScript" type="text/javascript"> function resetValue() { // 好きな食べ物の選択肢 sh_keihi = document.getElementById("sh_keihi"); // ジャンルの選択肢が変更された際の動作 ah_keihi = document.getElementById("ah_keihi"); ah_keihi.onchange = changeCategory; } // ジャンルの選択肢が変更された際の動作 function changeCategory() { // 変更後のカテゴリを取得 var changedCategory = ah_keihi.value; if (changedCategory == "1") { setLocalTrans(); } else if (changedCategory == "2") { setOutTrans(); } else { setOthers(); } } function setLocalTrans() { sh_keihi.textContent = null; // 選択肢1が1 var lTrans = [ {cd:"", label:"選択して下さい"}, {cd:"0", label:"あ"}, {cd:"1", label:"い"}, ]; lTrans.forEach(function(value) { var op = document.createElement("option"); op.value = value.cd; op.text = value.label; sh_keihi.appendChild(op); }); } function setOutTrans() { sh_keihi.textContent = null; // 選択肢1が2 var oTrans = [ {cd:"", label:"選択して下さい"}, {cd:"2", label:"か"}, {cd:"3", label:"き"}, ]; oTrans.forEach(function(value) { var op = document.createElement("option"); op.value = value.cd; op.text = value.label; sh_keihi.appendChild(op); }); } function setOthers() { sh_keihi.textContent = null; //選択肢1が3 var oOthers = [ {cd:"", label:"選択して下さい"}, {cd:"4", label:"さ"}, {cd:"5", label:"し"}, ]; oOthers.forEach(function(value) { var op = document.createElement("option"); op.value = value.cd; op.text = value.label; sh_keihi.appendChild(op); }); } function addList(obj) { // tbody要素に指定したIDを取得し、変数「tbody」に代入 var tbody = document.getElementById('list_main'); // objの親の親のノードを取得し(つまりtr要素)、変数「tr」に代入 var tr = obj.parentNode.parentNode; // tbodyタグ直下のノード(行)を複製し、変数「list」に代入 var list = tbody.childNodes[0].cloneNode(true); // 複製したノード「list」を直後の兄弟ノードの上に挿入 // (「tr」の下に挿入) tbody.insertBefore(list, tr.nextSibling); } function removeList(obj) { // tbody要素に指定したIDを取得し、変数「tbody」に代入 var tbody = document.getElementById('list_main'); // objの親の親のノードを取得し(つまりtr要素)、変数「tr」に代入 var tr = obj.parentNode.parentNode; // 「tbody」の子ノード「tr」を削除 tbody.removeChild(tr); } </script> コード

ソースコード

### 試したこと 複製の過程に問題があるのでは、と考えており、 関数の記載場所などを変えてみたりはしたのですが、うまくいきませんでした。 ※+ボタンを押して作成される、追加行はの選択肢2は、1行目の選択肢の選択の結果によるもので固定されてしまいます。  作成の都度選択肢1の選択結果に応じて、選択が変動するプログラムを意図しております。 #![イメージ説明](8ccfb8787e08dd07c7976dc9a157cf82.png) 不勉強で大変恐縮ですが、ご助力賜れますと幸いに存じます。

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

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

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

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

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

guest

回答2

0

この程度の量なら目で追えるから説明はいらないでしょ。
何個でもSELECTは連動しますよ。

js

1<!DOCTYPE html> 2<meta charset="UTF-8"> 3<title>sample</title> 4<style> 5 #LIST tbody tr:first-of-type, #LIST td select optgroup:last-of-type { display: none;} 6 #LIST { counter-reset: number 0; } 7 #LIST tbody tr th label:after { counter-increment: number 1; content: counter(number);} 8</style> 9 10<body> 11<table border="1" id="LIST"> 12 <thead> 13 <tr> 14 <th>No. 15 <th>追加/削除 16 <th>選択肢1 17 <th>選択肢2 18 19 <tbody> 20 <tr> 21 <th><label>No.</label> 22 <td> 23 <button type="button" value="add">+</button> 24 <button type="button" value="del">-</button> 25 <td> 26 <select name="ah_keihi"> 27 <option value="">≪選択してください≫ 28 <option value="a">近郊交通費 29 <option value="b">出張旅費 30 <option value="c">その他 31 <optgroup></optgroup> 32 </select> 33 <td> 34 <select name="sh_keihi" disabled> 35 <option value="">≪選択してください≫ 36 <option value="a0" class="a">37 <option value="a1" class="a">38 <option value="b0" class="b">39 <option value="b1" class="b">40 <option value="c0" class="c">41 <option value="c1" class="c">42 <optgroup></optgroup> 43 </select> 44</table> 45 46 47<script> 48 49function replaceTRSelects (e) { 50 let 51 selects = [...e.closest ('tr').querySelectorAll ('select')], 52 index = selects.indexOf (e) + 1, 53 value = e.value; 54 55 for (let i = index, s; s = selects[i]; i++) { 56 s.selectedIndex = 0; 57 if (value) { 58 let 59 optgroup = s.querySelector ('optgroup:last-of-type'), 60 [first,...options] = s.querySelectorAll ('option'); 61 62 for (let opt of options) 63 opt.classList.contains (value) 64 ? s.insertBefore (opt, optgroup) 65 : optgroup.appendChild (opt); 66 67 s.disabled = false; 68 value = s.value; 69 } 70 else 71 s.disabled = true; 72 } 73} 74 75 76function addRow (tr = null) { 77 let tbody = tr ? tr.parentNode: document.querySelector ('#LIST tbody'); 78 tbody.insertBefore (tbody.rows[0].cloneNode (true), tr); 79} 80 81 82function delRow (tr) { 83 if (2 < tr.rowIndex) 84 tr.remove (); 85} 86 87 88function handler ({ target: e, type }, tr) { 89 switch (event.type) { 90 case 'click' : 91 if ('button' === e.type) 92 if (tr = e.closest ('tr')) 93 switch (e.value) { 94 case 'add': addRow (tr); break; 95 case 'del' : delRow (tr); break; 96 } 97 break; 98 99 case 'change' : 100 if ('SELECT' === e.nodeName) 101 replaceTRSelects (e); 102 break; 103 } 104} 105 106//_____________________ 107 108addRow (); 109LIST.addEventListener ('click', handler, false); 110LIST.addEventListener ('change', handler, false); 111 112</script>

投稿2021/02/22 15:17

編集2021/02/26 10:24
babu_babu_baboo

総合スコア616

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

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

babu_babu_baboo

2021/02/22 15:44 編集

th label と optgroup は、突っ込まれそうかな?
safari13872021

2021/02/25 23:59

ご回答いただきありがとうございます。また確認と理解に時間がかかってしまい申し訳ありません。 また、trが追加されたり、別の関数を実装する際のために確認させていただきたいのですが、 ①html要素の閉じタグの記載がない場合がありますが、質問時の画像通りに区切ってしまって宜しいでしょうか。 意図的な部分があるでしょうか。 ②記載方法の部分で [first,...options]=〜の部分はどのような意味でしょうか。調べても同じような記載方法の解説が見当たりませんでした。 ③関数内のeとclosestの動作eから記述上1番近いtrのみが参照されるのでしょうか。それともtrが複数あればそれぞれを参照して、それ以降のqueryselectorなどの「select」などのタグで絞り込むような使い方も可能でしょうか。 今後プルダウンメニューのtrとは別に集計用のtrを作成したいと考えており、その際にご教示いただいた関数を妨げないか懸念しております。 試しにhtml側にtrを追加した場合、見かけ上は特に変化がないように感じられました。 ④また利用環境を記載していなかったのですが、internet explorerで実行した場合一部機能せず、MicrosoftEDGEで実行した場合は問題なく起動しました。IEで使う場合の注意点などありましたらご教示いただけますと幸いです。 ご質問ばかりで恐縮ですが、可能な範囲でご教示いただけますと幸いです。
babu_babu_baboo

2021/02/26 10:30 編集

基本的に私はショートコーディングをします。その上での回答です 1.閉じタグは省略できるものとできないものがあります。私は省略できるものは省略します。htmlの中に必要以外のものは置かない派です。 2.[f,...op] = [0,1,2,3]; f =0, op = [1,2,3] と同じ つまり <option>の最初の要素は動かしたくないので分離して代入。 querySelectorAll で集めた要素は、死んだノードリストであり配列ではない。そこで配列にして代入しているという意味もあるかな? 3. e.closest は querySelector の逆ですね。一番近い祖先の要素を返します。プログラムでは、<tr>要素の子要素の中の<select>群を集めています 集計用に追加するのであれば、<tbody>を複数記載します。むしろ<tfoot>が望ましい。 <tbody>の最初の<tr>は、スタイルシートによって隠されます。 つまり複数の<tbody>の最初の<tr>は、雛形そのものです。 同じテーブルの中においても<tbody>は雛形をもととして動きます。 関数を書くときは、それに特化せず汎用化できるように考えて作ります。 4.IEは忘れました。 提示したコードは、全般に「癖が強い」と思います。 でも慣れると助長的なコードが書けなくなります。 貴方のように尋ねられたのは初ですね。みんなコピペで動けばOK!な感じなのに… それからイベントは外側から監視します。過去の質問の中でそれでトラブっている人が非常に多い。回答者側もそれで満足しているし。 頑張ってください。
guest

0

idを指定して処理しているので無理ですね。
相対位置を使って連携して下さい
それともう少し簡便なサンプルにしたほうが良いと思います

投稿2021/02/22 10:10

yambejp

総合スコア116724

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問