電気ひつじ牧場

技術メモ

複数ページ間でチェックボックスの値を保持してsubmitする

ページャなどにより複数ページにチェックボックスが配置されている状況を考えます。
要件としては、
・ページ遷移しても以前チェックした値はチェックされたまま保持されている
・submitした際にチェックしてある値を別ページのものも含め全て送信する
というものがあるとします。
チェックした値をどこかに保持させる必要があるわけですが、cookieはjsから操作しづらいのでsessionStorageを使います。
なお以下のコードでは私の好みの関係でjQueryは使いません。

checkbox_page1.html

<!DOCTYPE html>
<html>
    <body>
        <form action='' method='POST' id='boxform'>
            <input type='checkbox' id='checkbox_1' name='boxes[]' value='1'>
            <label for='checkbox_1'>1</label>
            <input type='checkbox' id='checkbox_2' name='boxes[]' value='2'>
            <label for='checkbox_2'>2</label>
            <input type='checkbox' id='checkbox_3' name='boxes[]' value='3'>
            <label for='checkbox_3'>3</label>
            <input type='submit' id='submit'>
        </form>
        <a href='#'>1</a> | <a href='checkbox_page2.html'>2</a>
        <script src='checkbox_handler.js'></script>
    </body>
</html>

checkbox_page2.html

<!DOCTYPE html>
<html>
<body>
    <form action='' method='POST' id='boxform'>
        <input type='checkbox' id='checkbox_4' name='boxes[]' value='4'>
        <label for='checkbox_4'>4</label>
        <input type='checkbox' id='checkbox_5' name='boxes[]' value='5'>
        <label for='checkbox_5'>5</label>
        <input type='checkbox' id='checkbox_6' name='boxes[]' value='6'>
        <label for='checkbox_6'>6</label>
        <input type='submit' id='submit'>
    </form>
    <a href='checkbox_page1.html'>1</a> | <a href='#'>2</a>
    <script src='checkbox_handler.js'></script>
</body>
</html>

以上の2つのページ間で値を保持させたいとします。

checkbox_handler.js

const checkbox = document.getElementsByName('boxes[]');
const storage = sessionStorage;

document.addEventListener('DOMContentLoaded', () => {
    autoCheck();
    checkbox.forEach((element) => {
        element.addEventListener('change', (e) => {
            if (e.target.checked) {
                storage[e.target.id] = true;
            } else {
                storage.removeItem(e.target.id);
            }
        });
    });

    document.getElementById('boxform').addEventListener('submit', (e) => {
        e.preventDefault();
        const myForm = document.createElement('form');
        myForm.setAttribute('action', 'index.php');
        myForm.setAttribute('method', 'POST');
        const checkedValues = document.createElement('input');
        checkedValues.setAttribute('type', 'hidden');
        checkedValues.setAttribute('name', 'myCheckbox');
        checkedValues.setAttribute('value', joinSavedCheckBoxes());
        myForm.appendChild(checkedValues);
        document.getElementsByTagName('body')[0].append(myForm);
        myForm.submit();
        storage.clear();
    });
});

const joinSavedCheckBoxes = () => {
    const checkboxes = [];
    for(let i=0, len=storage.length; i<len; i++) {
        if(storage.key(i).indexOf('checkbox_') === 0) {
            checkboxes.push(storage.key(i));
        }
    }
    return checkboxes.join(',');
}

const autoCheck = () => {
    checkbox.forEach((element) => {
        if(storage[element.id]) {
            element.checked = true;
        }
    });
};

チェックのON/OFFでsessionStorageにcheckboxのIDを格納/除去します。submitが押下されたらフォームを作成し、sessionStorageから取り出した値をinput要素に入れて送信します。
sessionStorageをfor文で回してるのが辛い(keyを配列で取得できないっぽい?)

確認

1,6をチェックし、サーバー側のPHPスクリプトにvar_dump($_POST);を書いて中身を見てみる

array (size=1)
  'myCheckbox' => string 'checkbox_1,checkbox_6' (length=21)

あとはサーバー側でパースすればOK