【JavaScript】ボタンクリックで動的に入力フィールド(HTML要素)を追加・削除する方法

# 概要
- JavaScriptのjQueryを使って、「ボタンをクリックすると動的に入力欄が増えていく」という実装を行いました。本記事ではその方法を紹介します。

# 前提・実装方法
- 今回はdjangoを使っている中で実装しましたが、HTML部分とJavaScript部分だけなのでPythonは関係ありません。
- 以下の動作を想定します。
    - ページ（テンプレート）に最初に一つだけ入力フィールド（テキストフィールド）が表示される。
    - 「+」ボタンをクリックすると、新しい入力フィールドが追加される。それぞれ一意のIDが与えられる。
    - 「+」ボタンをクリックすると「-」削除ボタンも一緒に追加される。これをクリックすると追加した入力フィールドが削除できる
- 以上の操作により、ユーザーが必要な数だけ入力フィールドを追加できるものとしました。

# サンプルコード
- 今回は「IPアドレス」という入力フィールドが動的に増えるサンプルコードを紹介します。

```html
<!-- CSS省く　 -->

<div class="container ip-fields-container">
    <div class="row">
        <div class="col-sm-2 flex flex-center">
            <label for="">IP</label>
        </div>
        <div class="col-sm-4">
            <input type="text" id="" class="form-control" placeholder="" name="ip_addresses[]" value="">
        </div>
        <div class="col-sm-4">
            <button id="add-field-btn" type="button">+</button>
        </div>
    </div>
</div>


<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.11.2/js/jquery.dataTables.min.js"></script>

<!-- 動的に入力フィールドを増やすJS -->
<script>
    var fieldCount = 1;

    $(document).on('click', '#add-field-btn', function() {
        fieldCount++;
        var newField = $('<div class="row">' +
            '<div class="col-sm-2">' +
            '    <label for="ip' + fieldCount + '">IP</label>' +
            '</div>' +
            '<div class="col-sm-4">' +
            '    <input type="text" id="ip' + fieldCount + '" class="form-control" placeholder="" name="ip_addresses[]" value="">' +
            '</div>' +
            '<div class="col-sm-4">' +
            '    <button class="remove-field-btn" type="button">-</button>' +
            '</div>' +
            '</div>');

        $('.ip-fields-container').append(newField);
    });

    $(document).on('click', '.remove-field-btn', function() {
        $(this).closest('.row').remove();
    });
</script>
```

## 詳細に解説
- 以下は基礎的なこともまとめておいたので、知っている方はスルーくだされ。

## jQueryについて
- jQueryはJavaScriptのライブラリであり、HTML文書内でのDOM操作やイベント処理などを簡単に使えることで人気です。
- 最初にjQueryとDataTablesというライブラリのCDNを追加します。
- `$(document)`は、HTMLドキュメント全体を表すjQueryオブジェクト
- `.on('click', '#add-field-btn', function() { ... })`は、クリックイベントの監視とそのハンドラ関数の設定
- つまり、「ドキュメント内の`#add-field-btn`というIDを持つ要素がクリックされたときに、以下のハンドラ関数を実行するよ」という意味です。

### `id`と`fieldCount`について
- `id=""`は、入力フィールドの一意の識別子です。
- HTML（最初の方）では、空の値が指定。
- JSで追加される方は`id="ip' + fieldCount + '":`としています。`fieldCount`は「入力フィールドが動的に生成されるたびにインクリメントされる」変数です。これにより、各入力フィールドが一意のIDを持つことができます。
- スクリプト頭にある`fieldCount++`は、`fieldCount += 1`と同じ意味です。フィールドの数をカウントするための変数`fieldCount`の値を1増やします。

### `name`属性について
- `name="ip_addresses[]"`は、入力フィールドの名前属性です。
- フォームが送信される際は、この名前が使われます。
    - 例えば、djangoであれば`forms.py`ではこの名前`ip_addresses[]`で識別されます。私は今回、`forms.py`の`save()`メソッドにて、`ip_addresses[]`のリストの要素をfor文で取り出し、それぞれをDBに追加する、という処理を行いました。

### appendについて
- `var newField`は、新しいフィールドを作成するための変数です。この変数は、後続のコードで新しい要素を作成するために使用されます。`var newField`には、新しいフィールドのHTML要素を表すオブジェクトが代入されます。このオブジェクトは、`jQueryの $()`関数を使用して動的に作成されるものですね。
- `$('.ip-fields-container') `は、`.ip-fields-container`クラスを持つ要素を選択します。この要素は、既存のHTMLにある`<div class="container ip-fields-container">`のことです。
- `append(newField)`は、上記の`<div>`で囲まれた部分に、新しい要素を追加するよ、という意味になります。これにより、新しいフィールドが既存の要素内に追加されます。

### removeについて
- `$(this).closest('.row').remove();`は、クリックされた削除ボタンに最も近い`.row`要素を削除する処理です。この場合、最も近く追加されたテキストフィールドが削除されます。
    - `.closest('.row')`：クリックされた削除ボタンに最も近い親要素で、クラス名が`.row`である要素を取得できます