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

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

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

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

2098閲覧

連想配列から連動するセレクトボックスを作成したい

nakamu-

総合スコア3

JavaScript

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/02/10 05:34

編集2021/02/10 09:55

前提・実現したいこと

下記のような連想配列を使って分岐・連動するセレクトボックスを作りたいと思っております。

■一つ前の選んだ項目で絞ったセレクトボックスを追加したい
例えば、りんごが選択された時に、次のセレクトボックスの中身は「りんご」の中のplace一覧が表示され、
その次のセレクトボックスが「りんご」-「place(例えば青森県産)」に紐づくset - toyを表示させるイメージです。

商品の情報は紐付けしておきたいので、(例えば 「りんご - 青森産 - 2パックセット - おもちゃつき」 など)
セレクトボックスが5個くらいになった時に連想配列の階層がとんでもなく深くなってしまうのですが、
情報が多い場合この配列の書き方・使い方であっているのでしょうか??
別なやりかたの方が実装・運用が簡単という方法があればご教示時ください。

2つ目までは連動できるのですが、どうしても3つ目以上ができません。
3つ目以降を上の階層に紐づくセレクトボックスの作り方をご教示いただければと思います。

html

1<select id="selName" onchange="selParts(this);"></select> 2<select id="sel2"></select> 3<select id="sel3"></select> 4<select id="sel4"></select> 5<select id="sel5"></select>

現状の配列

javascript

1let data = [{ 2 cd: "1", 3 name: "りんご", 4 place:[ 5 {cd: "1",place: "青森県産", 6 set:[{cd:1,set:"2パックセット", 7 toy:[{cd:1,toy:"りんごのおもちゃ",}, 8 {cd:1,toy:"梨のおもちゃ",},] 9 }, 10 {cd:1,set:"3パックセット", 11 toy:[{cd:1,toy:"りんごのおもちゃ",}, 12 {cd:1,toy:"梨のおもちゃ",},] 13 }, 14 ] 15 }, 16 {cd: "2",place: "長野県産", 17 set:[{cd:1,set:"特別セット", 18 toy:[{cd:1,toy:"りんごのおもちゃ",}, 19 {cd:2,toy:"梨のおもちゃ",},] 20 }, 21 {cd:2,set:"激安セット", 22 toy:[{cd:1,toy:"りんごのおもちゃ",}, 23 {cd:2,toy:"梨のおもちゃ",},] 24 }, 25 ]}, 26 {cd: "3",place: "山形産", 27 set:[{cd:1,set:"2パック特別セット", 28 toy:[{cd:1,toy:"りんごのおもちゃ",}, 29 {cd:2,toy:"梨のおもちゃ",},] 30 }, 31 {cd:1,set:"3パック激安セット", 32 toy:[{cd:1,toy:"りんごのおもちゃ",}, 33 {cd:2,toy:"梨のおもちゃ",},] 34 }, 35 ]}, 36 ], 37 }, 38 { 39 cd: "2", 40 name: "バナナ", 41 place:[ 42 {cd: "1",place: "国産", 43 set:[{cd:1,set:"2パックセット", 44 toy:[{cd:1,toy:"バナナのおもちゃ",}, 45 {cd:1,toy:"おもちゃなし",},] 46 }, 47 {cd:1,set:"3パックセット", 48 toy:[{cd:1,toy:"パイナップルのおもちゃ",}, 49 {cd:1,toy:"ハンカチ",},] 50 }, 51 ] 52 }, 53 {cd: "2",place: "インドネシア産", 54 set:[{cd:1,set:"特別セット", 55 toy:[{cd:1,toy:"タオル",}, 56 {cd:2,toy:"ペン",},] 57 }, 58 {cd:2,set:"激安セット", 59 toy:[{cd:1,toy:"シール",}, 60 {cd:2,toy:"なし",},] 61 }, 62 ]}, 63 {cd: "3",place: "フィリピン産", 64 set:[{cd:1,set:"2パック特別セット", 65 toy:[{cd:1,toy:"シール",}, 66 {cd:2,toy:"フィリピンのおもちゃ",},] 67 }, 68 {cd:1,set:"3パック激安セット", 69 toy:[{cd:1,toy:"タオル",}, 70 {cd:2,toy:"シール",},] 71 }, 72 ]}, 73 ], 74 }, 75 ]

javascriptコード

javascript

1for (var i = 0; i < data.length; i++) { 2 let op = document.createElement("option"); 3 op.value = data[i].cd; 4 op.appendChild(document.createTextNode(data[i].name)); 5 document.getElementById("selName").appendChild(op); 6} 7 8 9 10function selParts(obj) { 11 var targetArr; 12 if (obj.value == "1") { 13 targetArr = data[0].place; 14 } else if (obj.value == "2") { 15 targetArr = data[1].place;; 16 } else { 17 targetArr = new Array(); 18 } 19 var selObj = document.getElementById('sel2'); 20 while (selObj.lastChild) { 21 selObj.removeChild(selObj.lastChild); 22 } 23 for (var i = 0; i < targetArr.length; i++) { 24 let op = document.createElement("option"); 25 op.value = targetArr[i].place; 26 op.text = targetArr[i].place; 27 selObj.appendChild(op); 28 } 29}

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

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

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

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

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

yambejp

2021/02/10 06:01

りんごとringoplaceが紐付いてないので、最初からdataに りんごのデータにplaceというデータを埋め込むほうがよいのでは?
nakamu-

2021/02/10 06:47

すいません。知識不足で申し訳ないのですが、おっしゃっているのは{ name: "りんご", place: "青森県産"}というようにするということでしょうか?? その場合の、nameの値が「りんご」のplaceだけを抽出する方法を教えていただけないでしょうか?
yambejp

2021/02/10 07:01

こんな感じということです let data = [{ cd: "1", name: "りんご", place:[ {cd: "1",place: "青森県産",}, {cd: "2",place: "長野県産",}, {cd: "3",place: "山形産",}, ], }, {・・・
yambejp

2021/02/10 07:02

appleplaceやbananaplaceなど名前に依存するような変数を果物が増えるたびに 作っていくのは非効率で管理もしづらいでしょう
nakamu-

2021/02/10 07:48

ありがとうございます!!!! 教えていただいたものにすると、「■セレクトボックス内で重複している項目は除外したい」という要望もあわせて解決できました!!!!
guest

回答1

0

ベストアンサー

回答が付かないようなので。

データの構造が私の好みではありません。
階層が深くなるとキーとなる名前に統一性が無いからです。
なので俺様仕様です。エラーチェックも殆んどしていません。
SELECT要素群の最後の値を見れば選ばれた経緯も理解できるでしょう!

青森県産の「サンふじ」が、大好きです。もう一度言っておきます!「サンふじ」が、大好きです。

js

1<body> 2<p> 3 <select id="selName"></select> 4 <select id="sel2"></select> 5 <select id="sel3"></select> 6 <select id="sel4"></select> 7<p> 8 <select class="p"></select> 9 <select class="p"></select> 10 11<script> 12 13class O { 14 constructor ([text, value = text, ds = false, s = false], group = '') { 15 this.option = new Option (text, value, ds, s); 16 this.group = group; 17 } 18 19 static create (...args) { return new this (...args)} 20} 21 22 23class S { 24 constructor (selects = [ ], data = [ ], first) { 25 this.selects = [...selects]; 26 this.data = data; 27 this.first = first; 28 29 let s = selects[0], d = data[0]; 30 this.replaceSelect (s, d); 31 this.replaceAfter (s) 32 } 33 34 replaceSelect (sel, opts = []) { 35 sel.length = 0; 36 if (this.first) 37 opts = [this.first, ...opts]; 38 opts.forEach (o=> sel.appendChild (o.option.cloneNode (true))); 39 } 40 41 replaceAfter (e) { 42 if (! this.selects.includes (e)) return; 43 let 44 val = e.value, 45 no = this.selects.indexOf (e) + 1, 46 sel = this.selects[no]; 47 48 console.log (this.selects.map (s=> s.value).join (', '));//値の確認 49 50 if (! sel) return; 51 this.replaceSelect (sel, this.data[no].filter (op=> op.group == val)); 52 this.replaceAfter (sel); 53 54 } 55 56 handleEvent ({target: e}) { 57 let n = this.selects.indexOf (e); 58 if (-1 < n) 59 this.replaceAfter (e); 60 } 61 62 static create (selects, data, first = new O(['--', '', true]), root = document) { 63 if (selects.length != data.length) 64 throw new Error ('長さが合わない'); 65 let obj = new this (selects, data, first); 66 root.addEventListener ('change', obj, false); 67 return obj; 68 } 69} 70 71let 72 o = O.create.bind(O),//呼び出しを省略するため 73 data0 = [ 74 o(["リンゴ", 1]),//[text, value, defaultSelected, selected] 75 o(["バナナ", 2]) 76 ], 77 data1 = [ 78 o(["青森県産",10], 1), 79 o(["長野県産",11], 1), 80 o(["山形産",12], 1), 81 82 o(["国産",20], 2), 83 o(["インドネシア産",21], 2), 84 o(["フィリピン産",22], 2), 85 ], 86 data2 = [ 87 o(["2パックセット", 100], 10), 88 o(["3パックセット", 101], 10), 89 90 o(["特別セット", 110], 11), 91 o(["激安セット", 111], 11), 92 93 o(["2パック特別セット", 120], 12), 94 o(["3パック激安セット", 121], 12), 95 96 o(["2パックセット", 200], 20), 97 o(["3パックセット", 201], 20), 98 99 o(["特別セット", 210], 21), 100 o(["激安セット", 211], 21), 101 102 o(["2パック特別セット", 220], 22), 103 o(["3パック激安セット", 221], 22), 104 ], 105 106 data3 = [ 107 o(["りんごのおもちゃ", 1000], 100), 108 o(["梨のおもちゃ", 1001], 100), 109 110 o(["りんごのおもちゃ", 1010], 101), 111 o(["梨のおもちゃ", 1011], 101), 112 113 o(["りんごのおもちゃ", 1100], 110), 114 o(["梨のおもちゃ", 1101], 110), 115 116 o(["りんごのおもちゃ", 1200], 120), 117 o(["梨のおもちゃ", 1201], 120), 118 119 o(["りんごのおもちゃ", 1210], 121), 120 o(["梨のおもちゃ", 1211], 121), 121 122 o(["バナナのおもちゃ", 2000], 200), 123 o(["おもちゃなし", 2001], 200), 124 125 o(["タオル", 2100], 210), 126 o(["ペン", 2101], 210), 127 128 o(["シール", 2110], 211), 129 o(["なし", 2111], 211), 130 131 o(["シール", 2200], 220), 132 o(["フィリピンのおもちゃ", 2201], 220), 133 134 o(["タオル", 2210], 221), 135 o(["シール", 2211], 221), 136 ] 137 138S.create (document.querySelectorAll ('select[id^="sel"]'), [data0, data1, data2, data3]); 139 140//__________ 141 142let 143 d0 = [o(['intel']), o(['amd'])], 144 d1 = [o(['win10'], 'intel'), o(['linux'], 'intel'), o(['win10'], 'amd'), o(['linux'], 'amd') ]; 145 146S.create (document.querySelectorAll ('.p'), [d0, d1], new O (["選んでね",""])); 147 148</script> 149

投稿2021/02/12 08:52

編集2021/02/12 09:03
babu_babu_baboo

総合スコア616

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

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

nakamu-

2021/02/12 11:44

ありがとうございます!!! 「サンふじ」食べてみようと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問