Help us understand the problem. What is going on with this article?

jQueryでフォームを動的に追加/削除

More than 1 year has passed since last update.

検索フォームを追加したいとご依頼あり。
最初からたくさんフォームを出しとくのもかっこ悪いし、
とはいえ一個一個要素を増やすのもめんどくさい。
追加ボタンで動的にまるっとコピーできないかしら、ってことでやってみました。
jQueryほんとべんり。

Add & Remove form elements dynamically
(2018/12/19変更:runnableがリンク切れしていたのでjsfiddleに引っ越し)

以下解説↓

元のフォーム

これがないと始まらない。
フォーム全体をform-blockとしてくくり、idに番号0を振っておきます。
中の要素も同じ番号。増やすのはform-block単位。

index.html
    <form method="post" action="confirm">
      <div class="form-block" id="form_block[0]">
        <!-- Closeボタン -->
        <span class="close" title="Close" style="display: none;">-</span>

        <p>Name:<input type="text" name="name[0]" id="name[0]" /></p>
        <p>Sex:
          <input type="radio" name="sex[0]" id="sex_male[0]" value="male" checked>male
          <input type="radio" name="sex[0]" id="sex_female[0]" value="female">female
        </p>
        <p>Memo:<textarea name="memo[0]" id="memo[0]" rows="3"></textarea></p>
      </div>

      <!-- Addボタン -->
      <div class="form-block" id="form_add">
        <span class="add" title="Add">+</span>
      </div>
    </form>

フォームの追加

Addボタンを押したら、一つ上のフォームをクローンします。
現在フォーム数はグローバル変数frm_cntで管理。

script.js
      var original = $('#form_block\\[' + frm_cnt + '\\]');
      var originCnt = frm_cnt;
      var originVal = $("input[name='sex\\[" + frm_cnt + "\\]']:checked").val();

frm_cntをインクリメントする前にオリジナル(一つ前のフォーム)オブジェクトを取得しておく。
ラジオボタンのvalueも取っておくのは後のため。

script.js
      frm_cnt++;

      original
          .clone()
          .hide()
          .insertAfter(original)
          .attr('id', 'form_block[' + frm_cnt + ']') // クローンのid属性を変更。
          .find("input[type='radio'][checked]").prop('checked', true)
          .end() // 一度適用する
          .find('input, textarea').each(function(idx, obj) {
              $(obj).attr({
                  id: $(obj).attr('id').replace(/\[[0-9]\]+$/, '[' + frm_cnt + ']'),
                  name: $(obj).attr('name').replace(/\[[0-9]\]+$/, '[' + frm_cnt + ']')
              });
              $(obj).val('');
          });

オリジナルからクローンします。
やっていることは上から順に、
 1. クローンする
 2. 一旦隠す
 3. オリジナルの後ろに突っ込む
 4. クローンしたform_blockのidを新しい番号に変更
 5. ラジオボタンのデフォルト値を設定
 6. 上記を一旦適用
 7. text及びtextareaのidとnameを新しい番号に変更、テキストの値をクリア

script.js
      // clone取得
      var clone = $('#form_block\\[' + frm_cnt + '\\]');
      clone.children('span.close').show();
      clone.slideDown('slow');

クローンができたので表示します。
クローズボタンも一緒に。

script.js
      // originalラジオボタン復元
      original.find("input[name='sex\\[" + originCnt + "\\]'][value='" + originVal + "']").prop('checked', true);

で、これ。
クローンしたとき、オリジナルのラジオボタンのチェックが消えてしまうんですよね。
なのでここで戻しています。

フォームの削除

フォーム内部に配置したCloseボタンを押すと、親フォームを削除します。
その後、全体的に番号の振り直しをします。
※[0]のフォームは消しません。

script.js
        var removeObj = $(this).parent();
        removeObj.fadeOut('fast', function() {
            removeObj.remove();
            // 番号振り直し
            frm_cnt = 0;
            $(".form-block[id^='form_block']").each(function(index, formObj) {
                if ($(formObj).attr('id') != 'form_block[0]') {
                    frm_cnt++;
                    $(formObj)
                        .attr('id', 'form_block[' + frm_cnt + ']') // id属性を変更。
                        .find('input, textarea').each(function(idx, obj) {
                            $(obj).attr({
                                id: $(obj).attr('id').replace(/\[[0-9]\]+$/, '[' + frm_cnt + ']'),
                                name: $(obj).attr('name').replace(/\[[0-9]\]+$/, '[' + frm_cnt + ']')
                            });
                        });
                }
            });
        });
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away