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

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

ただいまの
回答率

88.59%

セレクトボックスの選択肢を、配列の内容から動的に生成させたい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 643

rickey

score 24

配列の中の名前を、クラス構文を使って、動的にセレクトボックスに入力させています。
しかし、途中で配列の名前を追加すると、それ以降にセレクトボックスを作成した場合、追加された配列が生かされますが、既に作成済みのセレクトボックスには、古い配列のままとなります。

列)
配列 = [a,b]として、これを入れたセレクトボックスを3つ作る。
その後、配列にcさんを加えて、さらにセレクトボックスを2つ作る。
そうすると5つのセレクトボックスの選択肢は以下の通りとなる。

a,b
a,b
a,b
a,b,c
a,b,c

これを、
a,b,c
a,b,c
a,b,c
a,b,c
a,b,c

としたい。
試行錯誤して、なんとか書かれているコードでこれは実現できました。
既存のセレクトボックスの中身を削除→新しい配列で作ったセレクトボックスを挿入

としています。

【質問の内容】
(1)
既存のセレクトボックスの削除ができてはいるのですが、書き方が正しくなく、
どのように書けばいいのかを教えていただきたいです。

   //一度セレクトボックスを空にしないと、メンバーがどんどん追加されてしまう。
      for(let i = 0; i < selectMember[item_j].options.length + 100; i++) {
          selectMember[item_j].options[0]=null
        }

(2)
セレクトボックスの作成をクラス構文で行っているのですが、
クラス構文に全く触れずに、別途関数を作って、セレクトボックスを削除して追加して強引にコードを書きました。
クラス構文を利用して、これと同じことはできないでしょうか?

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Tab Menu</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <div class="container">
      <ul class="menu">
        <li><a href="#" class="active" data-id="participant_tab"></a></li>
        <li><a href="#" data-id="item_tab"></a></li>
        <li><a href="#" data-id="result_tab"></a></li>
      </ul>

<!--1)参加者--------------------------------------------->
      <section class="content active" id="participant_tab">

        <div class="member_area">
          <div class="subTitle">立て替えくれた人</div>
          <div class="add_member_area">
            <input type="text" id="memberName" placeholder="名前を入力">
            <button id="memberAddBtn" class="disabled">追加</button>
          </div>

          <div class="member_list_table">
          </div>

          <ul id="memberList">
            <div>主催者(削除不可)</div>
<!--
              <li class="memberList_li">
              <button class="delMember">'x'</button>
              <div class="div_memberName">名前</div>
              </li> 
-->        
          </ul>
        </div>

      </section>
<!--2)項目----------------------------------------------->      
      <section class="content" id="item_tab">
        <div class="add_item_btn_area">
          <div>立て替え項目</div>  
          <div id='itemBtnArea'>
            <button id="itemAddBtn">項目を追加する</button>
          </div>    

          <div class="add_item"> 

            <ul id="itemList">
<!--
              <li>
                <button class="delMember">×</button>
                <select class="selectMember">
                  <option>テスト</option> 
                  <option>テスト</option> 
                </select>
                  <input class="oneItemName" placeholder="項目">
                  <input class="oneItemPrice" placeholder="金額">               
              </li>
-->
            </ul>

          </div>
        </div>
        <button id="testBtn">項目一覧のセレクトボックスに新しい参加者(配列)の名前を追加する</button>
      </section>
<!--3)計算結果----------------------------------------------->     
      <section class="content" id="result_tab">

      </section>     
    </div>

    <script src="main.js"></script>
  </body>
</html>
'use strict';
{

//参加者タブ------------------------------------- 
//★100)メンバー追加ボタンを押した時------ 
  var memberListArray = ["主催者"];//  これを関数内に入れると、追加していけない。
  const memberAddBtn = document.getElementById('memberAddBtn');//メンバー追加ボタン
  const memberName_id = document.getElementById('memberName');//メンバー入力フォーム 
  const memberList_id = document.getElementById('memberList');//メンバーリストを追加していくul要素のid


// 110)メンバーを配列に加える
  function addMemberListArray() {
    memberListArray.push(memberName_id.value);
    console.log(memberListArray);
    memberName_id.value = '';//メンバーの入力欄をクリアする※これをどこに入れるで作動が変わる
    memberName_id.focus();
  }//addMemberListArray


//  メンバーリストを管理
  class DisplayMemberList{
   constructor(){
     this.lists=[];
   } //constructor

    setup(){ //ulにliを追加していく
      this.lists.forEach(index => {
        memberList_id.appendChild(index.getli())
      });     
    }//setup

    //ボタンを押して一行追加する
    go () {
      this.lists.push(new MemberListOneColumn());
      this.setup();
//      console.log(this.lists);
    }//go
  }//displayMemberList class


  class MemberListOneColumn {//リストの一行を管理
    constructor() {
//      <li class="memberList_li">
//      <button class="delMember">'x'</button>
//      <div>名前</div>
//      </li>
      this.li = document.createElement('li');
      this.li.classList.add('memberList_li');

      //deleteボタンの追加
      const deleteBtn = document.createElement('button');
      deleteBtn.classList.add('delMember');
      deleteBtn.textContent = 'x';
      this.li.appendChild(deleteBtn);

      //テキストの追加
      const div_memberName = document.createElement('div');
      div_memberName.classList.add('div_memberName')
      div_memberName.textContent = memberName_id.value;  
//      console.log(memberName_id.value);
      this.li.appendChild(div_memberName);

      //削除ボタンを押した時       
      deleteBtn.addEventListener('click', ()=> {
        var idx=[].indexOf.call(memberList_id.querySelectorAll('li'),this.li);  
        displayMemberList.lists.splice(idx,1);
        memberList_id.removeChild(this.li);  
        // 配列からもメンバーを削除する
        memberListArray.splice(idx+1,1);
        console.log(memberListArray)
      });

    }//constructor

      getli(){
        return this.li;
      }//getli
  }//MemberListOneColumn

  const displayMemberList = new DisplayMemberList();
  memberAddBtn.addEventListener('click', () => {
    if (memberName_id.value !==''){
      memberAddBtn.classList.remove('disabled');
    }else{ 
      memberAddBtn.classList.add('disabled');
    };
    if (memberAddBtn.classList.contains('disabled') === true){
      return;
    }  
    displayMemberList.go();//メンバーを一覧に表示させる
    addMemberListArray();//110)メンバーを配列に加える


//    checkMemberAreaBlank(); //101)名前の空欄チェック→110)メンバーを配列に加える
  })//memberAddBtn.click

//項目タブ-----------------------------------------------------------
  const itemAddBtn = document.getElementById('itemAddBtn') ;//メンバー追加ボタン
  const itemList_id = document.getElementById('itemList');//メンバーリストを追加していくul要素のid

//  //  アイテムリストを管理
  class DisplayItemList{
    constructor(){
      this.lists=[];
    } //constructor

    setup(){ //ulにliを追加していく
      this.lists.forEach(index => {
        itemList_id.appendChild(index.getli())
      });     
    }//setup

    //ボタンを押して一行追加する
    go () {
      this.lists.push(new ItemListOneColumn());
      this.setup();
      console.log(this.lists);
    }//go
  }//displayMemberList class

  class ItemListOneColumn {//リストの一行を管理
    constructor() {   
      this.li = document.createElement('li');
      this.li.classList.add('memberList_li');

      //セレクトボックス(メンバー名の追加)
      const selectMember_tag = document.createElement('select');
      selectMember_tag.classList.add('selectMember');
        //セレクトボックスに追加する選択肢
      for(var i=0;i<memberListArray.length;i++){
        const optionMember_tag = document.createElement('option')
        optionMember_tag.text = memberListArray[i];   //テキスト値
        selectMember_tag.appendChild(optionMember_tag);
      }      
      this.li.appendChild(selectMember_tag);

      //金額入力項目の追加
      const input_itemPrice = document.createElement('input');
      input_itemPrice.classList.add('oneItemPrice');
      input_itemPrice.placeholder = '金額'
      this.li.appendChild(input_itemPrice);  

      });

    }//constructor

    getli(){
      return this.li;
    }//getli
  }//MemberListOneColumn

  const displayItemList = new DisplayItemList();
  itemAddBtn.addEventListener('click', () => {
    displayItemList.go();//アイテムを一覧に表示させる
  })//memberAddBtn.click

//テストボタン処理----------------------------------------------------------
  const testBtn = document.getElementById('testBtn');
  const selectMember = document.getElementsByClassName('selectMember')//該当の項目
  testBtn.addEventListener('click',() => {


    for(let item_j = 0; item_j < selectMember.length; item_j++){
      var idx = selectMember[item_j].selectedIndex;       //インデックス番号を取得
      var who  = selectMember[item_j].options[idx].text;//選ばれている人の名前

        //一度セレクトボックスを空にしないと、メンバーがどんどん追加されてしまう。
      for(let i = 0; i < selectMember[item_j].options.length + 100; i++) {
          selectMember[item_j].options[0]=null
        }

        // セレクトボックスに新しい配列の内容を入れる   
        for(let i = 0; i < memberListArray.length; i++) { 
          const option_tag = document.createElement('option')
          option_tag.text = memberListArray[i]
          selectMember[item_j].appendChild(option_tag);
        }

        // もともとのテキストボックスの選択肢になるようにする
      var options = document.getElementsByClassName('selectMember')[item_j].options;
        for(var i = 0; i < options.length; i++){
          console.log(options[i].text)
          console.log(who)
          if ( options[i].text === who ){
            options[i].selected = true;
            break;
          };
      }; 
    }//項目の数だけループ   
  });

}//javascript
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

増えた場合はわかりますが、減ったときはどうするんでしょうか?
またa,bがb,aになった場合はどうするんでしょうか?
一部更新

sample

<script>
window.addEventListener('DOMContentLoaded', ()=>{
  document.querySelector('#btn').addEventListener('click',()=>{
    var s=document.createElement('select');
    var o=document.createElement('option');
    o.textContent="--";
    o.value="";
    s.appendChild(o);
    document.querySelector('#hoge').appendChild(s);
    document.querySelector('#list').value.split(",").forEach(x=>{
      var o=document.createElement('option');
      o.textContent=x;
      o.value=x;
      s.appendChild(o);
    });
    Array.from(document.querySelectorAll('#hoge select')).forEach(x=>{
      var cln=s.cloneNode(true);
      cln.value=x.value;
      /* もしくは cln.selectedIndex=x.selectedIndex; */
      x.parentNode.insertBefore(cln,x);
      x.parentNode.removeChild(x);
    });
  });
});
</script>
<input type="text" id="list" value="a,b">
<input type="button" value="add" id="btn">
<div id="hoge"></div>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/03 14:56

    増えた場合と同様に減らした場合も、セレクトボックスに反映させようとしています。また、abがbaになることはせず、配列の順番通りにセレクトボックス入れようと考えています。

    キャンセル

  • 2019/09/03 15:13

    > 増えた場合と同様に減らした場合も、セレクトボックスに反映させよう

    一応、すでに例示したサンプルがその内容に対応していると思います
    例)
    →当初a,b,cで3回追加して、それぞれa,b,cを選択する
    →a,bに変更して追加するとすでに追加したcだけ未選択になる

    キャンセル

  • 2019/09/05 11:05

    クラス構文を使わなくても、できる方法はいろいろありますね。ここまで新たにコードを書いてくださって本当にありがとうございます。現在、検索しながら、詳細を調べているところです。しっかり調べて、自分の物になるように勉強します。

    キャンセル

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

  • ただいまの回答率 88.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る