LoginSignup
3
0

More than 1 year has passed since last update.

【チェックボックス】trueとfalseのあいだ

Posted at

checkbox_indeterminate.png
チェックボックスの状態でON/OFF以外に第3の状態があるのをご存知ですか?
上記の画像の「トップス」の部分のindeterminateという状態がそれにあたります。

ARCHETYPではShopify ExpertとしてECサイトのテーマ開発やカスタマイズをやっているのですが、検索や絞り込みのUIに親子関係があるチェックボックスをよく実装します。
今回はそんな親子階層を利用したユーザーがわかりやすいチェックボックスUIをindeterminate を用いて実装する方法をご紹介します。

jQueryを利用した実装を紹介されていたWebSpaceBlog様の記事を参考にさせていただきました。

結果

最初に結果のcodepenを貼り付けておきます。

See the Pen 中途半端なcheckbox(vanilla) by kamipoo (@kamipoo) on CodePen.

解説

HTML

HTMLはごくごくシンプルにリストの入れ子にチェックボックスを入れています。
グループを括る親のinputのclassにparentを指定します。
子アイテムを括るulのclassにchildを指定します。
ちなみにindeterminateはタグ属性では設定できず、JavaScriptを用いて設定する必要があります。

<ul>
    <li><label><input type="checkbox" class="parent"> カテゴリ1</label>
      <ul class="child">
        <li><label><input type="checkbox"> アイテム1</label></li>
        <li><label><input type="checkbox" checked> アイテム2</label></li>
        <li><label><input type="checkbox"> アイテム3</label></li>
    </ul></li>
  
    <li><label><input type="checkbox" class="parent"> カテゴリ2</label>
      <ul class="child">
        <li><label><input type="checkbox"> アイテム1</label></li>
        <li><label><input type="checkbox" checked> アイテム2</label></li>
        <li><label><input type="checkbox"> アイテム3</label></li>
    </ul></li>
</ul>

JavaScript

jQueryのコードを元にVanilla化させていただきました。

処理1

子チェックボックスをクリックした際の動作を定義します。
子チェックボックスの属するグループのチェックされた数を比較して、親チェックボックスの状態を制御しています。

条件

  1. 全てがチェックされていればchecked = true indeterminate = false
  2. なにもチェックされていなければchecked = false indeterminate = false
  3. 上記以外は checked = false indeterminate = true

処理2

親チェックボックスをクリックした際の動作を定義します。
親チェックボックスのチェック状態を子チェックボックスに適用します。

document.addEventListener("DOMContentLoaded", () => {
  //子要素をクリックした時に親要素のチェック状態をコントロール
  document.querySelectorAll('.child').forEach((child) => {
    child.addEventListener('click', (e) => {
      const parent = child.closest('li').querySelector('input[type=checkbox]');
      const checkboxCount = child.querySelectorAll('input[type=checkbox]').length;
      const selectedCount = child.querySelectorAll('input[type=checkbox]:checked').length;
      if (checkboxCount === selectedCount) {
        parent.indeterminate = false;
        parent.checked = true;
      } else if(0 === selectedCount) {
        parent.indeterminate = false;
        parent.checked = false;
      } else {
        parent.indeterminate = true;
        parent.checked = false;
      }
    });
    let e = new Event('click');
    child.dispatchEvent( e );
  });
  
  //親要素をクリックした時に子要素のチェック状態をコントロール
  document.querySelectorAll('.parent').forEach((parent) => {
    parent.addEventListener('click', (e) => {
      parent.closest('li').querySelectorAll('.child input[type=checkbox]').forEach((items) => {
        items.checked = parent.checked;
      });
    });
  });
});

Shopifyのテーマ開発はjQueryや各種フレームワークを使用しているアプリが多くコンフリクトを起こすことがしばしばあり、ARCHETYPのエンジニアチームでは脱jQuery、Vanilla推奨で開発しています。

ARCHETYPでは、Shopifyのテーマ開発やアプリ開発をやりたいエンジニアを募集しております!
気になった方はお気軽にエントリーをお待ちしております!
https://www.archetyp.jp/recruit/

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0