前々回の記事で、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 属性が変更されていることが分かります。

