[JavaScript] チェックボックス・ラジオボタンの初期値をGETパラメーターで自動設定したい
- アーカイブページに検索用のチェックボックスやラジオボタンを置いたとき、検索実行後の画面にチェックした内容を残しておきたい場合があります
- どういう条件で検索したかチェックが残っていた方が絞り込まれた状態がわかりやすく、そこから更にチェックを追加して再検索、といった操作もしやすいです
- こういったフォームの制御はPHPで行うことが多いですが、get形式のフォームであればJavascriptでも制御できます
- ついでにtext、hiddenタイプの項目の初期値も設定します
動作イメージ
- チェックボックス、ラジオボタンを選択した状態で送信ボタンを押すと、読み込み後(読み込みが一瞬でわかりにくいですが)に選択状態を初期値として設定します
- リセットボタンを押すと選択状態をクリアします
サンプルコード
html
<form action="" method="get" class="set_initial">
<dl>
<dt>チェックボックス</dt>
<dd>
<label><input type="checkbox" name="cb[]" value="cb_01">チェック1</label>
<label><input type="checkbox" name="cb[]" value="cb_02">チェック2</label>
<label><input type="checkbox" name="cb[]" value="cb_03">チェック3</label>
</dd>
<dt>ラジオボタン</dt>
<dd>
<label><input type="radio" name="rd" value="rd_01">ラジオ1</label>
<label><input type="radio" name="rd" value="rd_02">ラジオ2</label>
<label><input type="radio" name="rd" value="rd_03">ラジオ3</label>
</dd>
<dt>テキストボックス</dt>
<dd>
<input type="text" name="txt" value="">
</dd>
</dl>
<input type="submit" value="送信">
<input type="reset" value="リセット">
</form>
Javascript
window.addEventListener('load', function() {
const forms = document.getElementsByClassName('set_initial');
// 対象となるフォームがなければ終了
if(!forms.length) { return; }
// 先頭の?を除いたパラメーターを取得
const searchParams = location.search.slice(1).split('&');
for(let i = 0; i < forms.length; i++) {
const inputItems = forms[i].getElementsByTagName('input');
for(let j = 0; j < inputItems.length; j++) {
const inputItem = inputItems[j];
const type = inputItem.getAttribute('type');
for(let k = 0; k < searchParams.length; k++) {
const params = searchParams[k].split('=');
if(params[0] != null && params[1] != null) {
const key = decodeURI(params[0]);
const value = decodeURI(params[1]);
// リセットボタン押下時のイベントを設定
if(type === 'reset') {
inputItem.addEventListener('click', function() {
location.href = location.href.replace(location.search, '');
}, false);
}
// 入力項目のnameとkeyが一致しないならスキップ
if(inputItem.getAttribute('name') === key) {
if(type === 'checkbox' || type === 'radio') {
if(inputItem.getAttribute('value') === value) {
inputItem.setAttribute('checked', 'checked');
}
}
else if(type === 'text' || type === 'hidden') {
inputItem.setAttribute('value', value);
}
else {
// dummy
}
}
}
}
}
}
}, false);
サンプルコードの解説
チェックボックスにつけるname属性
<label><input type="checkbox" name="cb[]" value="cb_01">チェック1</label>
<label><input type="checkbox" name="cb[]" value="cb_02">チェック2</label>
<label><input type="checkbox" name="cb[]" value="cb_03">チェック3</label>
- 複数項目にチェックが可能なチェックボックスは、値を配列で受け取る必要があります
- name属性には[]をつけることで、パラメーターを配列として受け取ることができます
入れ子になったループの構造について
for(let i = 0; i < forms.length; i++) {
〜〜〜
for(let j = 0; j < inputItems.length; j++) {
〜〜〜
for(let k = 0; k < searchParams.length; k++) {
〜〜〜
}
}
}
- Javascriptの処理は3つのループを入れ子にしています
- 1つ目は、配列「forms」の数分回すループです。サイドバーなど他のフォームが誤動作しないよう、初期値設定するフォームには「set_initial」クラスを設定します。このクラスが設置された「form」タグの数だけループ処理します
- 2つ目は、配列「inputItems」の数分回すループです。「form」内の「input」タグの数だけループします
- 3つ目は、配列「searchParams」の数分回すループです。get方式で渡されたパラメーターの数だけループします。ループ中のinputタグとパラメーターを比較して、初期値設定が必要な要素かチェックします
GETパラメーターの取得と加工
https://xxx.com/?cb%5B%5D=cb_01&cb%5B%5D=cb_02&rd=rd_03&txt=
- get方式で送信されると、URL末尾に「?」から始まるパラメーターが設定されます
- 各パラメーターは「&」で区切られています
// 先頭の?を除いたパラメーターを取得
const searchParams = location.search.slice(1).split('&');
- 「location.search」で「?」から始まるパラメーターが取得できます
- パラメーターに対して「slice」関数を使って先頭「?」を削除し、更に「split」関数を使って「&」で分割したパラメーターを配列にセットします
const params = searchParams[k].split('=');
const key = decodeURI(params[0]);
const value = decodeURI(params[1]);
- 個々のパラメーターは[name属性] = [value属性]といった形に「=」で分けられています
- 再度「split」関数を使って「=」で分割し、name属性の内容を変数「key」、value属性の内容を「value」にそれぞれセットします
チェックボックス・ラジオボタンを選択状態にする
if(inputItem.getAttribute('name') === key) {
if(type === 'checkbox' || type === 'radio') {
if(inputItem.getAttribute('value') === value) {
inputItem.setAttribute('checked', 'checked');
}
}
else if(type === 'text' || type === 'hidden') {
inputItem.setAttribute('value', value);
}
else {
// dummy
}
}
- 各inputタグの初期値を設定する処理です
- まずはループ中のkeyが、ループ中のinputタグに設定された「name」属性と一致するかを判定します
- 次にinputタグの「type」属性をチェックし、チェックボックスかラジオボタンであれば、更に「value」属性の内容と、getで渡された値である変数「value」の内容が一致しているかを判定し、一致しているならinputタグの「checked」属性を有効にします
- 選択形式ではない「text」と「hidden」については、素直に「value」属性に変数「value」の内容をセットして初期値とします
リセットボタンの処理
// リセットボタン押下時のイベントを設定
if(type === 'reset') {
inputItem.addEventListener('click', function() {
location.href = location.href.replace(location.search, '');
}, false);
}
- 今回紹介した初期値設定処理を行うと、従来のリセットボタンが機能しなくなってしまいます。リセットボタンを押して項目がクリアされた後に、getパラメーターで初期値が再設定されるからです
- そこで、リセットボタンの処理を拡張し、ボタンが押されたときにgetパラメーター(アドレスの「?」以降の内容)をクリアしたURLで再読み込みするようにしています
ご質問など受け付けています
記事の中でわかりにくかったところ、もっと知りたかったこと、間違っていることなど、何でもお気軽にご連絡ください。
ご連絡は下記フォームを利用いただくか、ツイッターアカウント@flat8migi宛てでもOKです。