前々回の記事で、JavaScriptを用いて動的に要素をコピーし追加する方法について書き、
前回の記事で、セレクトメニューの場合は一工夫必要であることに触れましたが
単純に要素をコピーするだけだと、ラジオボタンの場合も上手くいきません。
ラジオボタンで値を選択し、その状態で要素を追加しても
このように、ラジオボタンの場合は、値がおかしなことになってしまいます。
一行目のラジオボタンの選択が、消えてしまっていることがわかりますね。
これは、ラジオボタンのグルーピングで使用している name 属性までが、コピーされているために起こる事象です。
同じ name 属性を持っているタグが4つできてしまうために、グルーピングがおかしくなってしまうのですね。
(もちろん、行を追加していく度に、同じ name 属性を持つタグは、6つ、8つ、・・・と増えていきます)
この問題を回避する方法は幾つかありますが、今回は name 属性を動的に変更することで対処していきます。
ラジオボタン要素の作成
まずコピー対象のラジオボタン要素の作成です。
既に上で登場していますが、このようにhtmlを記述していきます。
<input type="radio" name="yn" value="Yes" checked="checked">Yes <input type="radio" name="yn" value="No" >No
name 属性を “yn” としています。要素をコピーするときには、この値を変更していきます。
name属性の変更
name属性の変更は単純に、1ずつ増加する数字を追加することで対応します。
追加用数字の変数を一つ定義しておき、要素コピーの関数が呼び出される都度インクリメントしたうえで、setAttribute メソッドにより name 属性にセットします。
let cnt = 1; // 追加用数字の変数を定義
(中略)
function addExample() {
++cnt; // 追加用数字をインクリメント
// 要素をコピー
let elements = document.getElementById("target");
let copied = elements.lastElementChild.cloneNode(true);
// コピー先ラジオボタンのname属性を変更
copied.children[3].setAttribute("name", "yn" + cnt);
copied.children[4].setAttribute("name", "yn" + cnt);
elements.appendChild(copied);
}
children[] で、指定した子要素を取得できます。今回は2つあるラジオボタンが各々4番目と5番目の子要素なので、配列の指定値としては3と4を設定しています。
サンプルコード
動作確認用の全体のサンプルコードはこんな感じ。
(前回の記事で入れた、セレクトメニューの値コピーも含まれたコードです。)
<html> <head> </head> <body> <button id="add">Add!</button> <div id="target"> <div> <select> <option>A</option> <option>B</option> <option>C</option> </select> <input type="text"> <input type="checkbox"> <input type="radio" name="yn" value="Yes" checked="checked">Yes <input type="radio" name="yn" value="No" >No <button>here</button> </div> </div> <script type="text/javascript"> let cnt = 1; const btn = document.getElementById("add"); function addExample() { ++cnt; let elements = document.getElementById("target"); let copied = elements.lastElementChild.cloneNode(true); // セレクトメニューの値をコピー let val = elements.lastElementChild.firstElementChild.selectedIndex; copied.firstElementChild.selectedIndex = val; // コピー先ラジオボタンのname属性を編集 copied.children[3].setAttribute("name", "yn" + cnt); copied.children[4].setAttribute("name", "yn" + cnt); elements.appendChild(copied); } btn.addEventListener("click", addExample, false); </script> </body> </html>
動作確認
これまでの処理を追加することで、選択したラジオボタンの値も
前要素に影響を及ぼすことなく、コピーすることができました。
要素をタグで確認すると、確かに name 属性が変更されていることが分かります。