Web開発

【初心者向け】JavaScriptでフォーム項目を動的に追加・削除する方法|コピペで使えるサンプルコード付き

スポンサーリンク

なぜ動的フォームが便利なのか?

アンケートやチェックリストのように、ユーザーが入力する項目数が決まっていないケースでは、フォーム項目を自由に追加・削除できると非常に便利です。

例えば、好きな食べ物を自由にいくつでも入力させたいときや、メールアドレスを家族分登録してもらいたいときなど、固定されたフォームでは対応しきれません。

今回ご紹介するのは、純粋なJavaScript(ライブラリ不要)で、フォーム項目を動的に追加・削除できるシンプルな実装例です。


HTML構造と初期表示の仕組み

基本となる HTML は以下のとおりです。
フォームを <form> タグで囲み、その外に「追加」ボタンを設置します。
このあと解説するJavaScriptによって、window.onload イベントで自動的に1つ目の入力欄が作成されます。

<div class="form-wrapper">
  <form id="form">
  </form>
  <div class="add-btn-area">
    <button class="add-btn" onclick="add_form_element();">追加</button>
  </div>
</div>

ページ読み込み時にフォーム項目を自動生成

window.onload イベントで add_form_element() を呼び出すことで、ページロード時に最初の入力欄が表示されます。

add_form_element() の処理詳細は次で説明を行います。

window.onload = function () {
  add_form_element();
};

add_form_element() の処理詳細

「追加」ボタンが押されると次の流れで要素が生成されます:

  1. 「削除ボタン」「追加ボタン」の有効制御を更新
  2. 現在のフォーム項目数を取得し、番号を決定
  3. ラベル(例: No 1, No 2…)を生成
  4. テキスト入力欄(<input type="text">)を生成
  5. 削除ボタンを生成

これらをまとめて <div> 要素に挿入し、フォーム本体へ追加し、削除ボタン・追加ボタンの有効/無効の設定を行います。

/**
 * フォームの追加
 */
function add_form_element() {
  
  // フォーム内の要素の数
  var formarea = document.querySelector('#form');
  var num = 0;
  if (formarea !== null) {
    num = formarea.childElementCount;
  }
  num++;
  
  // ラベルの作成
  var label = create_label(num);
  
  // 入力欄の作成
  var text_form = create_text_from(num);
  
  // 削除ボタンの作成
  var del_btn = create_delete_btn(num);
  
  // ラベル・入力欄・削除ボタンをdiv要素に追加
  var form_area = document.createElement('div');
  form_area.setAttribute('id', 'form_area_' + num);
  form_area.appendChild(label);
  form_area.appendChild(text_form);
  form_area.appendChild(del_btn);
  
  // フォームに要素を追加
  var form = document.getElementById('form');
  form.appendChild(form_area);
  
  // 削除ボタンの有効無効
  set_delete_btn_disabled();
  
  // 追加ボタンの有効無効
  set_add_btn_disabled();
};

ラベルの生成

今回のサンプルでは、「No1」「No2」など番号付きのラベルを付けていますが、フォームを追加する際、ユーザーに分かりやすくするために、入力欄だけではなくラベル等、他の要素も一緒に追加をすると思います。

  • createElement で、labelタグを追加できます。
/**
 * ラベル
 */
function create_label(num) {
  var label = document.createElement('label');
  var label_txt = document.createTextNode('No' + num);
  label.appendChild(label_txt);
  return label;
}

入力欄の生成:識別可能な id と name

入力欄には idname 属性を設定します。
これにより、JavaScriptから値を取得しやすく、フォーム送信時にもサーバー側で正しく処理できます。

  • createElement で、inputタグを追加できます。
  • setAttribute で、type 属性とid 属性と name 属性の追加ができます。
/**
 * 入力欄
 */
function create_text_from(num) {
  var text_form = document.createElement('input');
  text_form.setAttribute('type', 'text');
  text_form.setAttribute('id', 'form_' + num);
  text_form.setAttribute('name', 'form_' + num);
  return text_form;
}

削除ボタンの生成:タイプ指定と動的バインド

type="button" を指定しないと、クリックでフォームが送信されてしまうことがあります。
さらに、onclick 属性で行ごとに削除対象を指定し、動的バインドしています。

  • createElement で、buttonタグを追加できます。
  • setAttribute で、class 属性と type 属性と onclick 属性の追加ができます。
/**
 * 削除ボタン
 */
function create_delete_btn(num) {
  var btn = document.createElement('button');
  var btn_txt = document.createTextNode('削除');
  btn.appendChild(btn_txt);
  btn.setAttribute('class', 'del_btn');
  btn.setAttribute('type', 'button');
  btn.setAttribute('onclick', 'delete_form_element("form_area_' + num + '");');
  return btn;
}

delete_form_element() :削除&番号リセット

削除ボタンを押すと実行されるのが delete_form_element() です。

削除処理では以下を実行します:

  1. 該当フォーム行の削除
  2. 残ったフォーム行の id/ラベル/入力欄 ID・name/削除ボタンの再生成
  3. ボタン有効制御を再設定
/**
 * フォームの削除
 */
function delete_form_element(name) {
  // 対象フォームの削除
  var elem = document.getElementById(name);
  elem.remove();
  
  // 残っているフォームのラベル・IDの番号の振りなおしと削除ボタンの作り直し
  var forms = document.querySelector('#form').children;
  
  // 連番の振りなおし
  for (i = 0; i < forms.length; i++) {
    // フォームのIDの番号の付け直し
    forms[i].id = 'form_area_' + (i + 1);
    // ラベルの番号の付け直し
    forms[i].children[0].innerText = "No" + (i + 1);
    // 入力欄のIDの番号の付け直し
    forms[i].children[1].id = 'form_' + (i + 1);
    forms[i].children[1].name = 'form_' + (i + 1);
    // 削除ボタンは作り直し
    forms[i].children[2].remove();
    var btn = create_delete_btn(i + 1);
    forms[i].appendChild(btn);
  }
  
  // 削除ボタンの有効無効
  set_delete_btn_disabled();
  
  // 追加ボタンの有効無効
  set_add_btn_disabled();
};

「追加」「削除」ボタンのON/OFF制御

今回のサンプルでは、最大5件までフォームを追加できるように制限をかけています。

  • 追加ボタン:最大 5 件までとし、それ以上は無効化
  • 削除ボタン:項目が 1 件のみなら無効化、それ以外は有効化
/**
 * 追加ボタンの有効無効の設定
 */
function set_add_btn_disabled() {
  var form = document.getElementById('form');
  var buttons = form.getElementsByTagName('button');
  if (buttons.length < 5) {
    document.getElementsByClassName('add-btn')[0].disabled = false;
  }
  else {
    document.getElementsByClassName('add-btn')[0].disabled = true;
  }
}

/**
 * 削除ボタンの有効無効の設定
 */
function set_delete_btn_disabled() {
  var form = document.getElementById('form');
  var buttons = form.getElementsByTagName('button');
  if (buttons.length == 1) {
    buttons[0].disabled = true;
  }
  else {
    for (i = 0; i < buttons.length; i++) {
      buttons[i].disabled = false;
    }
  }
}

実装の注意ポイント

削除ボタンに type="button" を指定しないと、押した瞬間にフォームがsubmitされてしまいます。これを防ぐためにも、button要素には明示的に type 属性を付けることが大切です。

また、querySelector, childElementCount, appendChild など、基本的なDOM操作が多く使われています。JavaScriptの練習素材としても最適です。


CodePenで試せるデモ

以下のCodePenで、今回紹介したコードを実際に動かして試すことができます。

ぜひカスタマイズして使ってみてください!

参考資料(DOM操作のMDNリファレンス)

document.createElement()要素を生成

Element.setAttribute()属性を設定/更新

Node.appendChild()要素を子要素として挿入

Element.remove()要素をDOMから削除

Element.childElementCount子要素の数を取得

Element.querySelector()CSSセレクタで要素取得(最初の一致)

タイトルとURLをコピーしました