SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

HTMLのテーブルでチェック行の情報だけ処理するサンプル/PHP・JavaScript

目次

HTMLのテーブルでチェック行の情報だけ処理するサンプル/PHPJavaScript

HTMLのtableタグを使って対象を一覧して、行ごとのチェックボックスでチェックされた行のみを処理する・・なんてパターンは、とてもよく使います。

ただ、PHPJavaScriptを併用して、ボタンを押された後はPHP側でチェック行を処理する・・みたいな処理にはちょっと癖があって、知らないと意外にハマるようです。

今回、そうなった人向けにサンプルで説明したら、割合好評だったので、そのサンプルをネタに記事にしようと思います。

サンプルの概要

HTMLで3行分のテーブルを作り、行ごとにチェックボックスを置きます。

ヘダーのところにもチェックボックスを置いて、それをチェックするとすべての行のチェックボックスに連動するようにします。

あとは、適当にチェックをつけて、ボタンを押すと、下のほうに選択された行の情報と値の合計を計算して表示します。

初期表示はこんな感じ。

適当にチェックをつけると、ボタンが押せるようになります。

で・・ボタンを押すと、以下のような結果がボタンの下のほうに表示される。

こんな感じの動きのサンプルです。

ソース全文です

HTML・JavaScriptPHPを1ファイルにまとめて書いたソース全文です。

<html lang="jp">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="https://cdn.simplecss.org/simple.css">
        <script language="JavaScript" type="text/javascript">
            <!--
            function AllChanged(){
                var check =  document.getElementById('aaa');
                var checkarr = document.getElementsByName('bbb[]');

                for (var i=0; i<checkarr.length; i++){
                    if(check.checked === true){
                        checkarr[i].checked = true;
                    }else{
                        checkarr[i].checked = false;
                    }

                }
                if(check.checked === true){
                    document.getElementById('b1').disabled = false;
                    document.form.disp.value = "1";
                }else{
                    document.getElementById('b1').disabled = true;
                    document.form.disp.value = "0";
                }
            }

            function OneChanged(){
                var checkCount = 0;
                var check =  document.getElementById('aaa');
                var checkarr = document.getElementsByName('bbb[]');
                for (var i=0; i < checkarr.length; i++){
                    if(checkarr[i].checked === true){
                        checkCount += 1;
                    }
                }
                if(checkCount > 0){
                    document.getElementById('b1').disabled = false;
                    document.form.disp.value = "1";
                }else{
                    document.getElementById('b1').disabled = true;
                    check.checked = false;
                    document.form.disp.value = "0";
                }
            }
            //-->
        </script>

    </head>
    <body>
        <form action="" name="form" method="POST">
        <input type="hidden" name="disp" value="0"/>
        <table>
            <tr>
                <th><input type="checkbox" name="aaa" id="aaa" onClick="AllChanged();" /> </th>
                <th>KEY</th>
                <th>値</th>
            </tr>
            <tr>
                <td><input type="checkbox" name="bbb[]" value="AAAAAA,100000" onClick="OneChanged();" /></td>
                <td>AAAAAA</td>
                <td>100000</td>
            </tr>
            <tr>
                <td><input type="checkbox" name="bbb[]" value="BBBBBB,200000" onClick="OneChanged();" /></td>
                <td>BBBBBB</td>
                <td>200000</td>
            </tr>
            <tr>
                <td><input type="checkbox" name="bbb[]" value="CCCCCC,300000" onClick="OneChanged();" /></td>
                <td>CCCCCC</td>
                <td>300000</td>
            </tr>
        </table>
        <div>
            <button type="submit" name="b1" id="b1" disabled>ボタンサンプル</button>
        </div>
        </form>
        <div>
        <p>
        <?php
            if (isset($_POST["disp"])) {
                $disp = $_POST["disp"];
                if ($disp == "1") {
                    echo "画面更新前のチェック状況<br />";
                    $chk = $_POST["bbb"];
                    $result = 0;
                    if (!empty($chk)) {
                        foreach ($chk as $key => $val) {
                            $arr = explode(",", $val);
                            if (count($arr) >= 2) {
                                echo $arr[0] . "が選択されました。<br />";
                                $result += intval($arr[1]);
                            }
                        }
                        echo "合計は" . $result . "です。";
                    }
                }
            }
        ?>
        </p>
        </div>
    </body>
</html>

続けて、ポイントを説明します

ポイント1:JavaScriptチェックボックスの選択状態取得

例えば、以下のような単独のチェックボックスの場合

<input type="checkbox" name="aaa" id="aaa" onClick="AllChanged();" />

チェックボックスの取得とチェック状態の判定は以下のようにできます。

var check =  document.getElementById('aaa');

if(check.checked === true){}

 

テーブルに配置した複数行のチェックボックスの場合は

<input type="checkbox" name="bbb" value="AAAAAA,100000" onClick="OneChanged();" />

<input type="checkbox" name="bbb" value="BBBBBB,200000" onClick="OneChanged();" />

以下のように配列で取得してループで処理できます。

var checkarr = document.getElementsByName('bbb');
for (var i=0; i < checkarr.length; i++){
       if(checkarr[i].checked === true){
              checkCount += 1;
       }
 }

どちらの方法でも可能ですが、僕の場合は、ひとつの場合は「ById」、複数の場合は「ByName」で取得するようにしてます。

そうすることで、割とありがちな間違い

例えば、「var check =  document.getElementsByName('aaa');」のように単一のチェックボックスをByNameで取得して、ByIdの時と同じように「check.checked」で値を取得しようとする(undefinedでうろたえることになります)・・みたいなケアレスミスがが少しでも減らせると思ってますので。

なお、上記のサンプルなら「document.form.aaa.checked」のような書き方でも、チェックボックスのON・OFFを取得できますし、割とサンプルでこういう書き方をしている場合も多いですけど、DOMの階層が変わると、書き直さないといけなくなるなどデメリットも多いので、使わない癖をつけといたほうが良いと個人的には思ってます。

ポイント2:PHPでのチェックボックスのついた行の処理

PHPでチェックボックスの値は、Submit後「$_POST」・「$_GET」で受け取れます。

<input type="checkbox" name="bbb" value="AAAAAA,100000" onClick="OneChanged();" />

<input type="checkbox" name="bbb[]" value="BBBBBB,200000" onClick="OneChanged();" />

みたいに定義した複数のチェックボックスを取得するのも、formで「post」していれば上記例のように以下で受け取れます。

 $chk = $_POST["bbb"];

ただ、気をつけなければいけないのは「PHPで取得できるのは、チェックボックスがONであるものだけ」ということです。

なので、デスクトップアプリケーションみたいに、PHP側でテーブルの行を順に処理して、チェックがついてたら・・みたいなロジックを考えると、はまります。

さらに、例えば「<td>」タグの中身をPHPで取得する方法はなく、無理やりやろうとすると「input type="hidden"」みたいなPHPで取得可能な情報をセットしておかないといけないなど、何かと面倒だったりします。

なので、チェックのついた行の情報を処理したいときは、PHP側の処理に使いたい情報はチェックボックスのValueにあらかじめセットしておくのが一番簡単で確実です。

そうすれば

$chk = $_POST["bbb"];
if (!empty($chk)) {
       foreach ($chk as $key => $val) {}

}

のように、チェックがついた行のValueに設定した値をとりだして、処理できます。

サンプルでは、2つの値を渡したかったので、valueの中にカンマつなぎでセットして取り出してから分割したりしてますが、考え方は同じです。

まとめ

説明したときも、上記の2つのポイントがわかれば、サンプルソースは簡単に理解できるといってもらえました。

なので、他のこまごました部分は、特に説明を書きませんが1つだけ補足です。

  <input type="hidden" name="disp" value="0"/> 

の隠し項目は、PHP側の処理で使ってます。

PHPをサンプルのように書いていると、当たり前ですが、初期表示のときにも実行されてしまいます。

その時に、余計なメッセージを表示しないように、この「disp」と名前をつけた隠し項目が「1」なら処理するみたいな書き方にして、それを抑制してます。

あと、当たり前ですけど、サンプルはちゃんとPHPが動くWebサーバー(nginxなど)を立ち上げて動かさないとダメで、HTMLなど拡張子を変えてダブルクリックで開いたりしても動きませんのでご注意を。

こんなもんですかね。

ではでは。