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

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

ただいまの
回答率

87.36%

セレクトボックスで選択で新規セレクトボックス追加

解決済

回答 1

投稿

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

score 41

セレクトボックスで選択肢を選ぶと、
下に同じセレクトボックスと削除ボタンが表示されるところまではできています。

セレクトボックスでAを選択して新規セレクトボックスを追加します。
同じセレクトボックスで今度はBを選択すると、
セレクトボックスがさらに追加されてしまいます。
一つのセレクトボックスで選択して追加できる新規セレクトボックスは
一つにしたいのですが、
どのようにすればよろしいでしょうか。

制限を設ければよいのだろうとは思うのですが、
具体的な方法がわかりません。

また、「選択してください」を選択したときは、新規セレクトボックスを追加しないようにするため「選択してください」(name="select-default")以外を選択時のみに、
新規セレクトボックスを追加するように(!== 'select-default')としたのですが、
うまくいきません。

どのようにすればよいのか、ご教授いただけませんでしょうか。

 <table id="t-table">
  <thead>
    <tr>
      <th>リスト選択</th>
      <th>リスト名</th>
      <th>追加/削除</th>
    </tr>
  </thead>

  <tbody id="table-tbody">
    <tr>
      <td>
        <select name="rule_original" class="changeList">
          <option value="select-default">選択してください</option>
          <option value="select-a">A</option>
          <option value="select-b">B</option>
          <option value="select-c">C</option>
        </select>
      </td>
      <td>A</td>
      <td>
      <input value="-" type="button" class="removeList" />
      </td>
    </tr>
  </tbody>
</table>
#t-table {
  width: 100%;
  font-size: 14px;
  border-collapse: collapse;
}

#t-table th,
#t-table td {
  border: 1px solid #ccc;
  padding: 12px 8px;
  text-align: center;
}

#t-table th {
  background-color: #a33337;
  color: #fff;
}

#t-table input,
#t-table select {
  width: 100px;
  cursor: pointer;
}

#t-table i {
  font-size: 18px;
  color: #7cb342;
}

#t-table input[type='button'] {
  background-color: #f0f0f0;
  border: 1px solid #aaa;
  border-radius: 2px;
  box-shadow: 0 1px 2px #999;
  font-size: 14px;
}

#table-tbody tr:first-child {
  display: none;
}
 $(document).ready(function() {
  // CSSで非表示にした1行目の行を複製し、その行の下に挿入
  $('#table-tbody>tr')
    .clone(true)
    .insertAfter($('#table-tbody>tr'));


//選択肢によって削除ボタンを表示
$(function(){
    $('select[name="rule_original"]').change(function() {
        if ($('select[name="rule_original"] option:selected').val() == 'select-default')
          $('#table-tbody>tr')
              .eq(0)
              .clone(true)
              .insertAfter(
        $(this)
          .parent()
          .parent(),
      );
    });
});


// 行を削除する
  $(document).on('click', '.removeList', function() {
    $(this)
      .parent()
      .parent()
      .remove();
  });
});
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

こんにちは

一つのセレクトボックスで選択して追加できる新規セレクトボックスは
一つにしたいのですが、
どのようにすればよろしいでしょうか。

行を追加する処理を行う前に、changeイベントの発生した select が、最下行に含まれるものであるかどうかを判定して、最下行にあるものでないならば、何もせず return させればよいと思います。

また、「選択してください」を選択したときは、新規セレクトボックスを追加しないようにするため「選択してください」(name="select-default")以外を選択時のみに、
新規セレクトボックスを追加するように(!== 'select-default')としたのですが、
うまくいきません。

ご質問にあるコードでは、 以下のとおり、!== ではなく == となっています。

if ($('select[name="rule_original"] option:selected').val() == 'select-default')

また、 select-default と比較すべき、 .val() で値を取得する option を取ってくるためのセレクタが正しくないです。

上記を踏まえて、以下のように修正しました。

$(document).ready(function() {
    // CSSで非表示にした1行目の行を複製し、その行の下に挿入
    $('#table-tbody>tr')
        .clone(true)
        .insertAfter($('#table-tbody>tr'));


    //選択肢によって削除ボタンを表示
    $('.changeList').change(function() {
        if ($('.changeList').index(this) !== $('.changeList').length-1)
          return;        
        if ($('option:selected', this).val() !== 'select-default')
            $('#table-tbody>tr')
            .eq(0)
            .clone(true)
            .insertAfter(
                $(this)
                .parent()
                .parent()
            );
    });


    // 行を削除する
    $(document).on('click', '.removeList', function() {
        $(this)
            .parent()
            .parent()
            .remove();
    });
});

動作確認のため、上記のコードは、以下の jsFiddle の修正案1のほうに上げています。

上記の修正案1のコードの中で、ご質問にある1点目の

一つのセレクトボックスで選択して追加できる新規セレクトボックスは
一つにしたいのですが、
どのようにすればよろしいでしょうか。

に対応したのが、以下の部分

if ($('.changeList').index(this) !== $('.changeList').length-1)
    return;     


です。2点目の

また、「選択してください」を選択したときは、新規セレクトボックスを追加しないようにするため「選択してください」(name="select-default")以外を選択時のみに、
新規セレクトボックスを追加するように(!== 'select-default')としたのですが、
うまくいきません。

について修正した箇所は、行を追加するかどうか判定する if 条件

if ($('option:selected', this).val() !== 'select-default')

の部分です。上記の修正案1では、ご質問に挙げられている2点のほか、以下の修正もしています。

  • 選択されたときに行を追加する処理を囲んでいた、不要な$(・・・); を削除
  • セレクタ select[name="rule_original"] だと長いので、 .changeList で置き換え

さらに、もう少し見通しよくするならば、 selectでchange が発生したときに、行を追加する条件は

  • そのchange の発生したselectが表の最下行のものであって、かつ、選択された値が select-default ではないこと

なので、この条件を満たすかどうかの判定をひとまとめに関数にして、条件を手短かに書ける if が一つあれば済むようにします。以下では、この判定のための関数をJQuery のプラグインとして書いた例です。

    $.fn.canAddRow = function() {
        return (
            $('.changeList').index(this) === $('.changeList').length - 1 &&
            $('option:selected', this).val() !== 'select-default'
        );
    };

以下の修正案2は上記の canAddRow を使って、行を追加できるselect がどうかを判定する部分を整理したものです。

以上、参考になれば幸いです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/24 10:18

    非常にわかりやすいご説明ありがとうございます。
    一部説明した内容に沿っておらず失礼しました。
    canAddRowのプラグイン作成あたりは、よくわかっていないので
    掘り下げて学びたいと思いました。

    キャンセル

  • 2019/07/24 10:36

    どういたしまして。解決されたようでよかったです 👏
    プラグインを作れるようになると、よく使う処理をひとまとめにしておけるので便利です。

    キャンセル

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

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

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