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

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

ただいまの
回答率

88.80%

動的に追加したフォームの内容をサーバーで受け取りたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,080

baron3

score 16

 前提・実現したいこと

・動的に追加、削除できるフォームを作りたい
・新たに追加されたフォームのValue値をサーバー側で受け取りたい

フォームはドロップダウンでカテゴリを選び、テキストで文字列を入力できるタイプのものです。
参考画像

 該当のソースコード

<div class="md-form input-group">
    <div id="form-block" class="md-form input-group">
        <div class="dropdown input-group-prepend">
            <button class="btn btn-primary m-0 dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" value="">Dropdown</button>
            <ul class="dropdown-menu">
                <li><a href="#" class="dropdown-item" value="aaa">aaa</a></li>
                <li><a href="#" class="dropdown-item" value="bbb">bbb</a></li>
                <li><a href="#" class="dropdown-item" value="ccc">ccc</a></li>
                <li><a href="#" class="dropdown-item" value="ddd">ddd</a></li>
            </ul >
            <input type="hidden" class="form-control" id="dropdown-value" name="dropdown-value" aria-label="" value="">
        </div>
        <input type="text" class="form-control" aria-label="Text input with dropdown button">
    </div>
</div>
<div class="mx-auto text-center">
    <button type="button" value="+" class="btn btn-sm btn-default add"></button>
    <button type="button" value="-" class="btn btn-sm btn-default del" disabled></button>
</div>
$(function(){
    $('.dropdown-menu .dropdown-item').click(function(){
        // ドロップダウン項目の表示を変更
        var visibleItem = $('.dropdown-toggle', $(this).closest('.dropdown'));
        var dropdown_value = $(this).attr('value');
        visibleItem.text(dropdown_value);
        // input[type=hidden]にドロップダウン項目を入れる
        var hidden_form = $(this).closest('.dropdown-menu').next();
        hidden_form.val(dropdown_value);
    });

     // +ボタン(class="add")がクリックされたら
    $(document).on("click", ".add", function () {
      //今あるフォームの数を取得
        var count = $('div[id^=form-block]').length;
        var originalForm = $('#form-block');

        // formが4つになったら.addをdisabled
        if(count===4){
            $('.add').prop("disabled", true);
        }else{
            //.delを押せるように変更
            $('.del').prop("disabled", false);
        }

        originalForm
        .clone(true)
        .insertAfter(originalForm)
        .attr('id', 'form-block[' + count + ']');
    });        

    // -ボタン(class="del")がクリックされたら
    $(document).on("click", ".del", function () {
        var count = $('div[id^=form-block]').length;

        // formが1つになったら.dellをdisabled
        if(count===1){
            $('.del').prop("disabled", true);
            }
        var originalForm = $('form-block[' + count + ']');
        originalForm.remove();
    });
});

 試したこと・問題

オリジナルのフォームformAをコピーして追加することはできました。
しかし新たに追加したフォーム(formB)のドロップダウン項目を変更するとformAのドロップダウン項目が変更されます。
また、追加したフォームを削除することができません。

初めて質問させて頂きます。わかりにくいところなどご指摘いただけますと幸いです。
よろしくお願いします。

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

Laravel5.5
Bootstrap4.1.3
jquery3.3.1

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

比較が間違ってます。=では代入になってしまいます(この場合常に真)。-ボタンも同様。

//if(count=4){
if (count === 4) {

削除時の要素取得の記述ミスを追加。

$('#form-block\\[' + (count - 1).toString() + '\\]');

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/22 10:45 編集

    ご回答ありがとうございます!これは凡ミスです。
    当初(>=)としていたのを修正した際に忘れていたのだと思います。
    (===)にしても依然問題は解決しません。
    質問内容は修正します!

    キャンセル

  • 2018/10/22 10:59

    削除時の要素取得について追記しました。
    「formBのドロップダウン項目を変更するとformAのドロップダウン項目が変更され」るのは再現できていないので不明です。

    キャンセル

  • 2018/10/22 17:12

    最後の方の、
    var originalForm = $('form-block[' + count + ']'); の後に、console.log(originalForm); として確認をしてみてください。
    x_xさんの書いているように(count - 1)としなければ、最後に追加したIDが指定できていませんよー。

    キャンセル

check解決した方法

0

解決しました。全ソースは最後に書きます。
回答くださった先輩方、ありがとうございました。大変参考になりました。
Bootstrap4のButtons with dropdownsを使って同じようなことをしたい方がいらっしゃるかもしれないのでまとめておきます。同志よ共に頑張りましょう!
また、もっとこうした方がいい等アドバイスがございましたら頂けますと幸いです。

結論から言うと、

 〇 originalForm.clone()
 ✕ originalForm.clone(true)


クローンしたフォームにtrueが入っていたことが大きな原因でした。
trueを入れると設定したイベントもクローンしてしまう為、「formBのドロップダウン項目を変更するとformAのドロップダウン項目が変更」されていたようです。正確にはformBのドロップダウンボタンを押すとformAのドロップダウンが開いていました。フォームが重なってたので気づかなかった。。

今回実装する必要があったのは主に4つでした。
1.ドロップダウンの項目を変更する(Bootstrap4のソースをコピペしても項目が変更できない)
2.フォームを増やす
3.フォームを減らす
4.サーバーでフォームの内容を受け取ることができるように紐づけを行う

最後の4つ目は、フォームをコピーしただけだとname属性が被るので思った通りになりません。

<input type="hidden" class="form-control" id="id_type" name="id_type" aria-label="" value="">

実装のポイントは次の3つと考えました。
1.追加したフォームにもイベントを適用
2.追加したフォームを特定できようにIDを動的に変化
3.追加したフォームのname属性を動的に変化

1つ目はドロップダウン項目の選択にイベントを使っているため、コピーしたフォームでも同じイベントを使えるようにする必要があります。なので、".on"を使う必要がありました。これを使うことで後から動的に追加された要素にもイベントを適用することができます

2と3は追加ボタンが押された時にIDなどを書き換えました。
今回は”.length”を使ってform-blockで始まる要素がいくつあるか取得して、その数字に+1したものをIDやname属性に入れています。フォームを追加していくとこの様なHTMLが出来上がります。

id=form-block[1]
  input[type=hidden] name=form_type[1]
id=form-block[2]
  input[type=hidden] name=form_type[2]
id=form-block[3]
  input[type=hidden] name=form_type[3]
コード

 全ソース

<div class="md-form input-group">
    <div id="form-block[1]" class="md-form input-group">
        <div id="btn" class="dropdown input-group-prepend">
            <button id="btn-id" class="btn btn-primary m-0 dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" value="">ID</button>
            <ul class="dropdown-menu">
                <li><a href="#" class="dropdown-item" value="aaa">aaa</a></li>
                <li><a href="#" class="dropdown-item" value="bbb">bbb</a></li>
                <li><a href="#" class="dropdown-item" value="ccc">ccc</a></li>
            </ul >
            <input type="hidden" class="form-control" id="form_type" name="form_type[1]" aria-label="" value="">
        </div>

        <input type="text" class="form-control"id="input_form" name="input_form[1] aria-label="Text input with dropdown button">
    </div>
</div>
$(function(){
    "use strict";
    var select = function(e){
        //form-blockを特定
        var dropdown_view = $(this).closest('.dropdown').parent();
        var dropdown_value = $(this).attr('value');
        dropdown_view.find('.dropdown-toggle').text(dropdown_value);
        // input[type=hidden]にドロップダウン項目を入れる
        var id_type = $(this).closest('.dropdown-menu').next();
        id_type.val(dropdown_value);
    }

    var addbtn = function(e){
        var count = $('div[id^=form-block]').length;
        var originalForm = $('#form-block\\[' + count +'\\]');

        //formが合計4つ(3つ増えたら)になったら.addをdisabled
        if(count===3){
            $('.add').prop("disabled", true);
        }

        //.delを押せるように変更
        $('.del').prop("disabled", false);

        //フォームをコピー 
        var copiedForm = originalForm
        .clone()
        .insertAfter(originalForm)
        .attr('id', 'form-block[' + (count + 1) + ']');


        copiedForm
        .find('#form_type')
        .attr('name', 'form_type[' + (count + 1) + ']')
        .val('');
     //コピーしたフォームの値を初期化
        copiedForm
        .find('.dropdown-toggle')
        .text('id');
        copiedForm
        .find('#input_form')
        .attr('name', 'input_form[' + (count + 1) + ']')
        .text('');

    }

    var delbtn = function(e){
        var count = $('div[id^=form-block]').length;
        // formが残り1つになったら
        if(count===2){
            $('.del').prop("disabled", true);
            $('.add').prop("disabled", false);
        }
        var originalForm = $('#form-block\\[' + count + '\\]');
        originalForm.remove();
    }

    $(document).on("click", ".dropdown-menu .dropdown-item", select);
    $(document).on("click", ".add", addbtn);      
    $(document).on("click", ".del", delbtn);

});

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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