LoginSignup
89
106

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-07-07

検索フォームを追加したいとご依頼あり。
最初からたくさんフォームを出しとくのもかっこ悪いし、
とはいえ一個一個要素を増やすのもめんどくさい。
追加ボタンで動的にまるっとコピーできないかしら、ってことでやってみました。
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 + ']')
                            });
                        });
                }
            });
        });
89
106
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
89
106