[Tips] Lighning Web Componentのdatatableで、チェックボックスのオンとオフを検知しわける

2023.02.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Salesforce の Lightning Web Component の datatable にて、行を選択するチェックボックスのオンとオフを区別して検知する方法です。

datatableは次のように、selected-rowsにチェック状態と同期する配列selectedRowsを指定し、onrowselectionにdatatableにてチェックをオン、オフした際に起動するハンドラとしてhandleRowSelectionを指定しています。

<lightning-datatable
    key-field="Id"
     :
    selected-rows={selectedRows}
    onrowselection={handleRowSelection}
>
</lightning-datatable>

JavaScriptでは、handleRowSelectionメソッドでgetPlusOrMinusメソッドを使って、チェックを追加したのか、外したのかの判定を取得しています。

import { LightningElement } from 'lwc';
export default class SomeComponent extends LightningElement {
    selectedRows = [];

    // :
    // 諸々初期化など
    // :

    handleRowSelection(event) {
        // チェックを追加したのか、外したのかを取得する
        const plusOrMinus = this.getPlusOrMinus(event.detail.selectedRows, selectedRows, (a, b) => {
            if ( a.length > 0 && b.length > 0 ) {
                return a.Id === b.Id;
            } else {
                return false;
            }
        });
        if ( plusOrMinus > 0 ) {
            // チェックを追加した時の処理を書く
        } else if ( plusOrMinux < 0 ) {
            // チェックを外した時の処理を書く
        }
    }

    /* チェックを追加したのか、外したのかを判定する */
    getPlusOrMinus(left, right, compareFunction) {
        const intersection = this.intersectArray(left, right, compareFunction);
        const diffLeft = this.diffArray(left, intersection, compareFunction);
        const diffRight = this.diffArray(right, intersection, compareFunction);
        if ( diffLeft.length > diffRight.length ) {
            return 1;
        } else if ( diffLeft.length < diffRight.length ) {
            return -1;
        } else {
            return 0;
        }
    }

    /* 配列の差分を得る */
    diffArray(left, right, compareFunction) {
        return left.filter(leftValue =>
            !right.some(rightValue => 
                compareFunction(leftValue, rightValue)
            )
        );
    }

    /* 配列の積集合を得る */
    intersectArray(left, right, compareFunction) {
        return left.filter(leftValue =>
            right.some(rightValue =>
                compareFunction(leftValue, rightValue)
            )
        );
    }

selectedRowsアトリビュートはhandleRowSelectionが呼ばれた時点ではチェックのオン/オフを問わず、操作する前の状態が入っています。また、event.detail.selectedRowsには操作した後の状態が入っています。

getPlusOrMinusメソッドで行なっていることは次の通りです。

  1. event.detail.selectedRowsselectedRowsで共通の要素(積集合: intersection)をとる
  2. event.detail.selectedRowsselectedRowsからそれぞれ積集合(1で得た結果)を引く
  3. 2で得た結果の長さを比較して、event.detail.selectedRowsから積集合を引いた長さの方が長ければチェックをオンにしたと判定する。逆に短ければチェックをオフにしたと判定する。

getPlusOrMinusdiffArrayintersectArrayでは配列の各要素の一致を判定するためのロジックをcompareFunctionとして引数で渡すようにしています。そのため、要素として含むオブジェクトの構造が異なる同士の配列でも利用することができます。