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

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

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

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

Q&A

解決済

1回答

1543閲覧

addEventListener内でif文は使用できないでしょうか。

TakuTakahashi

総合スコア10

JavaScript

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

0グッド

0クリップ

投稿2021/07/10 11:29

編集2021/07/10 13:27

前提・実現したいこと

A,B,C3つのプルダウンメニューをグループにして、1ページに2グループ繰り返します。
A,B,Cはすでに選択肢が決まっていて、Aで選択したものに対してB,Cで選択できる要素が絞り込まれます。

AのプルダウンメニューにAddEventListnerをつけてAをselectedで判定し、B,Cで使えないoptionにdisabledを付け、2回for文で繰り返そうとしています。ところが、addEventListner内でAのselectedが1の場合、2の場合、とif文を書くと、最初の文だけしか効かず、2つ目以降のelse ifが反応してくれません。1つ目を選択した後は、B,Cが固定されてしまいます。2つ目を選択してもB,Cは1つ目の条件になってしまいます。

該当のソースコード

javascript

1const selItem = document.querySelectorAll("select"); 2for (let i = 1; i < 6; i += 3) { 3 selItem[i].setAttribute("disabled", true); 4} 5for (let j = 2; j < 6; j += 3) { 6 selItem[j].setAttribute("disabled", true); 7} 8 9for (let k = 0; k < 6; k += 3) { 10 selItem[k].addEventListener("click", function(evt) { 11 //同じグループのAが選択されたらB,Cのdisabledを外す 12 selItem[k + 1].disabled = false; 13 selItem[k + 2].disabled = false; 14 //Aが変更された場合はB,Cの選択可能オプションが変わるのでB,Cは選択を初期化する 15 selItem[k + 1].selectedIndex = 0; 16 selItem[k + 2].selectedIndex = 0; 17 //Aのoption1つ目 18 if (selItem[k].value == "1") { 19 //Bの制限。Aのvalueが1の場合Bは1,2番目のみ選択可能 20 selItem[k + 1].options[3].setAttribute("disabled", true); 21 selItem[k + 1].options[4].setAttribute("disabled", true); 22 //Cの制限。Aのvalueが1の場合Cは1から6番目のみ選択可能 23 for (let c = 7; c < 12; c++) { 24 selItem[k + 2].options[c].setAttribute("disabled", true); 25 } 26 } 27 28 //Aのoption2つ目 29 else if (selItem[k].value == "2") { 30 //Bの制限。Aのvalueが2の場合Bは1,2,3番目のみ選択可能 31  selItem[k + 1].options[4].setAttribute("disabled",true); 32 //Cの制限。Aのvalueが2の場合Cは4から11番目のみ選択可能 33 for (let c = 1; c < 12; c++) { 34 selItem[k + 2].options[c].setAttribute("disabled", true); 35 } 36 evt.stopPropagation(); // イベントの伝播を止める 37 } 38 }); 39}

HTML

1//A-1 2<select> 3 <option value="" selected="selected">選択 ...</option> 4 <option value="1">11日</option> 5 <option value="2">12日</option> 6</select> 7//B-1 8<select> 9 <option value="" selected="selected">選択 ...</option> 10 <option value="1">田中</option> 11 <option value="2">佐藤</option> 12 <option value="3">藤井</option> 13 <option value="4">伊藤</option> 14</select> 15//C-1 16<select> 17 <option value="" selected="selected">選択 ...</option> 18 <option value="1">9時</option> 19 <option value="2">10時</option> 20 <option value="3">11時</option> 21 <option value="4">12時</option> 22 <option value="5">13時</option> 23 <option value="6">14時</option> 24 <option value="7">15時</option> 25 <option value="8">16時</option> 26 <option value="9">9時〜12時の間</option> 27 <option value="10">13時〜15時の間</option> 28 <option value="11">13時〜15時の間</option> 29</select> 30//A-2 31<select> 32 <option value="" selected="selected">選択 ...</option> 33 <option value="1">理系</option> 34 <option value="2">文系</option> 35</select> 36//B-2 37<select> 38 <option value="" selected="selected">選択 ...</option> 39 <option value="1">田中</option> 40 <option value="2">佐藤</option> 41 <option value="3">藤井</option> 42 <option value="4">伊藤</option> 43</select> 44//C-2 45<select> 46 <option value="" selected="selected">選択 ...</option> 47 <option value="1">9時</option> 48 <option value="2">10時</option> 49 <option value="3">11時</option> 50 <option value="4">12時</option> 51 <option value="5">13時</option> 52 <option value="6">14時</option> 53 <option value="7">15時</option> 54 <option value="8">16時</option> 55 <option value="9">9時〜12時の間</option> 56 <option value="10">13時〜15時の間</option> 57 <option value="11">13時〜15時の間</option> 58</select>

試したこと

独学者で行き詰まってしまいました。ご教示いただけると幸いです。よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

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

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

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

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

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

m.ts10806

2021/07/10 11:49

インデントのおかしさは直してください。 このかっこ{} の対応が全然見えない中でなんもないです。 タイトルだけに答えると「No」
Jon_do

2021/07/10 11:51

htmlを追記してください。
TakuTakahashi

2021/07/10 13:28

早速ご回答いただきありがとうございます。当初10回繰り返す、としていましたがHTML追加に伴い2回に簡略化しました。B,Cで指定するoptionも変更しました。
TakuTakahashi

2021/07/10 15:15

m.ts10806さん、Jon_doさん、この度は稚拙な質問に素早くご回答いただきまことにありがとうございました。お陰様で解決いたしました。またご縁がありましたら何卒よろしくお願いいたします。
guest

回答1

0

ベストアンサー

おそらく以下の部分が原因です。

javascript

1// 誤 2// if(selItem[k].value="1") 3 4//正 5if(selItem[k].value=="1")

selItem[k].value="1"は"1"が代入され常にtruthyなので、必ずそのifブロックが実行されてしまいます。

追加の質問に対する回答

1. optionにdisabledを指定する処理は記述してあるが、disabledを取り除く処理が無い

Aで1を選択したときには、Bの3と4がdisabledになります。
その後、Aで2を選択したときにはBの4をdisabledにしていますが、3のdisabledは解除されていないので結果的に1と同じ状況になっています。

2. Cの制限のfor文の範囲が間違っている

「Aのvalueが2の場合Cは4から11番目のみ選択可能」のはずが、「1~11を選択不可」にしています。

javascript

1const selItem = document.querySelectorAll("select"); 2 3for (let i = 1; i < 6; i += 3) { 4 selItem[i].setAttribute("disabled", true); 5} 6for (let j = 2; j < 6; j += 3) { 7 selItem[j].setAttribute("disabled", true); 8} 9 10for (let k = 0; k < 6; k += 3) { 11 selItem[k].addEventListener("click", function(evt) { 12 //同じグループのAが選択されたらB,Cのdisabledを外す 13 selItem[k + 1].disabled = false; 14 selItem[k + 2].disabled = false; 15 //Aが変更された場合はB,Cの選択可能オプションが変わるのでB,Cは選択を初期化する 16 selItem[k + 1].selectedIndex = 0; 17 selItem[k + 2].selectedIndex = 0; 18 19 /***** 追加:disabledの初期化 *****/ 20 const selB = selItem[k + 1]; 21 const selC = selItem[k + 2]; 22 for (let item of selB.options) item.removeAttribute("disabled"); 23 for (let item of selC.options) item.removeAttribute("disabled"); 24 /***** 追加ココまで *****/ 25 26 //Aのoption1つ目 27 if (selItem[k].value == "1") { 28 //Bの制限。Aのvalueが1の場合Bは1,2番目のみ選択可能 29 selItem[k + 1].options[3].setAttribute("disabled", true); 30 selItem[k + 1].options[4].setAttribute("disabled", true); 31 //Cの制限。Aのvalueが1の場合Cは1から6番目のみ選択可能 32 for (let c = 7; c < 12; c++) { 33 selItem[k + 2].options[c].setAttribute("disabled", true); 34 } 35 } 36 37 //Aのoption2つ目 38 else if (selItem[k].value == "2") { 39 40 //Bの制限。Aのvalueが2の場合Bは1,2,3番目のみ選択可能 41 selItem[k + 1].options[4].setAttribute("disabled", true); 42 //Cの制限。Aのvalueが2の場合Cは4から11番目のみ選択可能 43 44 /***** 修正:範囲 *****/ 45 for (let c = 1; c < 5; c++) { 46 selItem[k + 2].options[c].setAttribute("disabled", true); 47 } 48 evt.stopPropagation(); // イベントの伝播を止める 49 } 50 }); 51} 52

投稿2021/07/10 11:59

編集2021/07/10 14:04
k4a

総合スコア983

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

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

k4a

2021/07/10 12:06

m.ts10806さんの言う通り、インデントは整えてください。 VSCodeなどのエディタなら拡張機能ですぐに直せます。 https://jsfiddle.net/ などのオンラインIDE等を使用しても良いと思います。 また、Jon_doさんのhtmlを追記してくださいというもの尤もです。 回答者が動作を確認しようとしてもhtmlが無いとすぐに確認できません。
TakuTakahashi

2021/07/10 13:25

==のご指摘ありがとうございます。htmlの掲載に伴い簡略化したこともあってか、Aに対するB,Cが意図した動きにならなくなりました。グループに対応していないのと、やはりelse ifが効きません。
k4a

2021/07/10 14:18 編集

回答を追加しました。 これは今回の質問に直接関連はしないのでコメントに書きますが、2点修正したほうが良さそうなことがあります。 1. selItem[k + 1]の用な記述は可能な限り減らす 追加回答では`const selB = selItem[k + 1];`の用に変数を定義しました。 selItem[k + 1]やselItem[k + 2]が色んな場所で出てくると後々自分でもこれが何を示しているのかわからなくなります(多分)。 できるだけわかりやすい変数に格納して、配列での指定はなくしましょう(selBは微妙な命名かもしれません)。 2. イベントハンドラは`click`より`change`の方が良い clickイベントはselect選択時とoption選択時の2回呼ばれます。 また、選択に変更がなくても呼ばれます。 changeイベントはoption選択時、かつ選択が変更された場合のみ呼ばれます。
TakuTakahashi

2021/07/10 15:16 編集

遅くまでお付き合いいただきまことにありがとうございました。おかげさまで意図した通りに動きました !あまりに手に負えず組織内のアンケートのためExcelファイルの集計にしようかと考え直していたところご回答を目にしました。厚く御礼申し上げます。またご縁がありましたらどうぞよろしくお願いいたします。 ```javascript const selItem = document.querySelectorAll("select"); for (let i = 1; i < 6; i += 3) { selItem[i].setAttribute("disabled", true); } for (let j = 2; j < 6; j += 3) { selItem[j].setAttribute("disabled", true); } for (let k = 0; k < 6; k += 3) { selA.addEventListener("change", function(evt) {  const selA = selItem[k]; const selB = selItem[k + 1]; const selC = selItem[k + 2]; //同じグループのAが選択されたらB,Cのdisabledを外す selB.disabled = false; selC.disabled = false; //他で制限された状態を解放する for (let item of selB.options) item.removeAttribute("disabled"); for (let item of selC.options) item.removeAttribute("disabled"); //Aが変更された場合はB,Cの選択可能オプションが変わるのでB,Cは選択を初期化する selB.selectedIndex = 0; selC.selectedIndex = 0; //Aのoption1つ目 if (selItem[k].value == "1") { //Bの制限。Aのvalueが1の場合Bは1,2番目のみ選択可能 selB.options[3].setAttribute("disabled", true); selC.options[4].setAttribute("disabled", true); //Cの制限。Aのvalueが1の場合Cは1から6番目のみ選択可能 for (let c = 7; c < 12; c++) { selC.options[c].setAttribute("disabled", true); } } //Aのoption2つ目 else if (selA.value == "2") { //Bの制限。Aのvalueが2の場合Bは1,2,3番目のみ選択可能  selB.options[4].setAttribute("disabled",true); //Cの制限。Aのvalueが2の場合Cは4から11番目のみ選択可能 for (let c = 1; c < 5; c++) { selC.options[c].setAttribute("disabled", true); } evt.stopPropagation(); // イベントの伝播を止める } }); } ```
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問