React Tree Grid 検索フィルター

    React Tree Grid の Ignite UI for React 検索フィルター機能を使用すると、データのコレクション内の値を検索するプロセスが可能になります。この機能のセットアップが簡単になり、検索入力ボックス、ボタン、キーボード ナビゲーション、その他の便利な機能を使用して実装できるため、ユーザー エクスペリエンスがさらに向上します。ブラウザーにはネイティブなコンテンツ検索機能がありますが、ほとんどの場合で IgrTreeGrid は表示範囲外の行列を仮想化します。そのため、ネイティブ ブラウザー検索は DOM の一部でないため仮想化セルでデータを検索できません。IgrTreeGrid では、React Material テーブル ベースのグリッドの拡張により、検索 API を使用した仮想コンテンツの検索が可能です。

    React 検索の例

    次の例は、すべての列と行を検索できる検索入力ボックスと、各列の特定のフィルタリング オプションを備えた IgrTreeGrid を表しています。

    EXAMPLE
    DATA
    TSX
    CSS

    このサンプルが気に入りましたか? 完全な Ignite UI for Reactツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。

    React 検索の使用

    Tree Grid のセットアップ

    グリッドを作成してからデータをバインドします。コンポーネントにカスタム スタイルも追加しました。

    <IgrTreeGrid ref={gridRef} data={data} autoGenerate={false} primaryKey="ID" foreignKey="ParentID" allowFiltering={true} height="100%" width="100%">
        <IgrColumn field="Name" dataType="string" sortable={true}></IgrColumn>        
        <IgrColumn field="ID" dataType="number" sortable={true}></IgrColumn>        
        <IgrColumn field="Title" dataType="string" sortable={true}></IgrColumn>        
        <IgrColumn field="Age" dataType="number" sortable={true}></IgrColumn>        
        <IgrColumn field="HireDate" dataType="date" sortable={true}></IgrColumn>  
    </IgrTreeGrid>
    tsx

    では、IgrTreeGrid の検索 API の準備をしましょう。検索したテキストの保存、また大文字小文字の区別や完全一致 (またはそのいずれか) に使用するプロパティを作成できます。

    const gridRef = useRef<IgrTreeGrid>(null);
    const [caseSensitiveSelected, setCaseSensitiveSelected] = useState<boolean>(false);
    const [exactMatchSelected, setExactMatchSelected] = useState<boolean>(false);
    const [searchText, setSearchText] = useState('');
    tsx

    React 検索ボックス入力

    検索入力を作成します。searchText を新しく作成したinput要素の value プロパティにバインドし、inputOccured イベントをサブスクライブすることで、ユーザーによるすべての searchText の変更を検出できます。これにより、IgrTreeGridfindNext メソッドと findPrev メソッドを使用して、searchText が出現するすべての箇所をハイライト表示し、(呼び出したメソッドに応じて) 次 / 前の箇所にスクロールできるようになります。

    findNextfindPrev メソッドの両方に 3 つの引数があります。

    • Text: string (検索テキスト)
    • (オプション) CaseSensitive: boolean (検索で完全一致するかどうか、デフォルト値は false)。
    • (オプション) ExactMatch: boolean (検索で完全一致するかどうか、デフォルト値は false)。

    完全一致で検索した場合、検索 API は SearchText と完全一致 (大文字小文字の区別を含む) するセル値のみ結果としてハイライト表示します。たとえば、文字列 'software' と 'Software' は大文字小文字を区別しない場合は完全一致となります。

    上記のメソッドは number 値を返します (IgrTreeGrid で指定した文字列が含まれる回数)。

    const handleOnSearchChange = (event: IgrComponentValueChangedEventArgs) => {
        setSearchText(event.detail);
        nextSearch(event.detail, caseSensitiveSelected, exactMatchSelected);
    }
    
    <IgrInput name="searchBox" value={searchText} onInput={handleOnSearchChange}>
    </IgrInput>
    tsx

    検索ボタンの追加

    ボタンの各クリック イベント ハンドラー内で findNextfindPrev メソッドを呼び出して検索や検索結果をナビゲーションするためのボタンを作成します。

    const prevSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findPrev(text, caseSensitive, exactMatch);
    }
    
    const nextSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findNext(text, caseSensitive, exactMatch);
    }
    
    <IgrIconButton variant="flat" name="prev" collection="material" onClick={() => prevSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
    </IgrIconButton>
    <IgrIconButton variant="flat" name="next" collection="material" onClick={() => nextSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
    </IgrIconButton>
    tsx

    キーボード検索の追加

    ユーザーは矢印キーと Enter キーで結果を移動できます。PreventDefault メソッドのデフォルト キャレットの移動を防止する検索入力の keydown イベントを処理し、ユーザーが押したキーに基づいて findNext/findPrev メソッドを呼び出します。

    const searchKeyDown = (e: KeyboardEvent<HTMLElement>) => {
        if (e.key === 'Enter' || e.key === 'ArrowDown') {
            e.preventDefault();
            nextSearch(searchText, caseSensitiveSelected, exactMatchSelected);
        } else if (e.key === 'ArrowUp') {
            e.preventDefault();
            prevSearch(searchText, caseSensitiveSelected, exactMatchSelected);
        }
    }
    
    const handleOnSearchChange = (event: IgrComponentValueChangedEventArgs) => {
        setSearchText(event.detail);
        gridRef.current.findNext(event.detail, caseSensitiveSelected, exactMatchSelected);
    }
    
    <div onKeyDown={searchKeyDown}>
        <IgrInput name="searchBox" value={searchText} onInput={handleOnSearchChange}></IgrInput>
    </div>
    tsx

    大文字と小文字の区別と完全一致

    次に完全一致の検索で大文字と小文字を区別するかどうかをユーザーが選択できるようにします。この目的のために、IgrChip コンポーネントをブール値の状態変数とともに使用して、IgrChip が選択されているかどうかを示すことができます。

    const [caseSensitiveSelected, setCaseSensitiveSelected] = useState<boolean>(false);
    const [exactMatchSelected, setExactMatchSelected] = useState<boolean>(false);
    
    const handleCaseSensitiveChange = (event: IgrComponentBoolValueChangedEventArgs) => {
        setCaseSensitiveSelected(event.detail);
        nextSearch(searchText, event.detail, exactMatchSelected);
    }
    
    const handleExactMatchChange = (event: IgrComponentBoolValueChangedEventArgs) => {
        setExactMatchSelected(event.detail);
        nextSearch(searchText, caseSensitiveSelected, event.detail);
    }
    
    <IgrChip selectable={true} onSelect={handleCaseSensitiveChange}>
        <span>Case Sensitive</span>
    </IgrChip>
    <IgrChip selectable={true} onSelect={handleExactMatchChange}>
        <span>Exact Match</span>
    </IgrChip>
    tsx

    保持

    IgrTreeGrid のフィルターやソート、レコードの追加や削除をする場合を想定します。そのような処理の後、現在の検索が自動的に更新されて SearchText に一致するテキストが保持されます。更に検索がページングで動作し、IgrTreeGridPerPage プロパティの変更時もハイライト表示が保持されます。

    アイコンの追加

    その他のコンポーネントを使用するためにユーザー インターフェイスを作成し、検索バー全体のデザインを向上します。検索入力の左側に検索または削除アイコン、検索オプションのチップ、右側にはマテリアル デザイン アイコンと Ripple スタイルのボタンを組み合わせたナビゲーションを表示できます。

    まず、マテリアル アイコン付きの 2 つのリップル スタイルのボタンを追加して、入力の右側に検索ナビゲーション ボタンを作成します。click イベントのハンドラーはそのままで findNext/findPrev メソッドを呼び出します。

    • 以下は CaseSensitiveExactMatch プロパティを切り替えるチップを表示する方法です。チェックボックスの代わりにスタイリッシュなチップを 2 つ表示します。チップをクリックすると、どちらのチップがクリックされたかによって各ハンドラーを呼び出します。
    const prevSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findPrev(text, caseSensitive, exactMatch);
    }
    
    const nextSearch = (text: string, caseSensitive: boolean, exactMatch: boolean) => {
        gridRef.current.findNext(text, caseSensitive, exactMatch);
    }
    
    <div slot="suffix">
        <IgrIconButton variant="flat" name="prev" collection="material" onClick={() => prevSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
            <IgrRipple></IgrRipple>
        </IgrIconButton>
        <IgrIconButton variant="flat" name="next" collection="material" onClick={() => nextSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
            <IgrRipple></IgrRipple>
        </IgrIconButton>
    </div>
    tsx

    次に、入力の左側に検索アイコンとクリア アイコンを追加します。

    const clearSearch = () => {
        setSearchText('');
        gridRef.current.clearSearch();
    }
    
    <div slot="prefix">
        {searchText.length === 0 ? (
            <IgrIconButton variant="flat" name="search"  collection="material">
            </IgrIconButton>
            ) : (
            <IgrIconButton variant="flat" name="clear" collection="material" onClick={clearSearch}>
            </IgrIconButton>
        )}
    </div>
    tsx

    最後に、すべてを組み合わせた結果が以下のようになります:

    useEffect(() => {
        registerIconFromText("search", searchIconText, "material");
        registerIconFromText("clear", clearIconText, "material");
        registerIconFromText("prev", prevIconText, "material");
        registerIconFromText("next", nextIconText, "material");
    }, []);
    
    <IgrInput name="searchBox" value={searchText} onInput={handleOnSearchChange}>
        <div slot="prefix">
            {searchText.length === 0 ? (
                <IgrIconButton variant="flat" name="search"  collection="material">
                </IgrIconButton>
                ) : (
                <IgrIconButton variant="flat" name="clear" collection="material" onClick={clearSearch}>
                </IgrIconButton>
            )}
        </div>
        <div slot="suffix">
            <IgrIconButton variant="flat" name="prev" collection="material" onClick={() => prevSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
                <IgrRipple></IgrRipple>
            </IgrIconButton>
            <IgrIconButton variant="flat" name="next" collection="material" onClick={() => nextSearch(searchText, caseSensitiveSelected, exactMatchSelected)}>
                <IgrRipple></IgrRipple>
            </IgrIconButton>
        </div>
    </IgrInput>
    tsx
    Ignite UI for React | CTA Banner

    既知の問題と制限

    制限 説明
    テンプレートを使用したセル内の検索 検索機能のハイライト表示が、デフォルトのセルテンプレートに対してのみ機能する問題。カスタム セル テンプレートを含む列がある場合、ハイライト表示が機能しないため、列フォーマッタなどの代替アプローチを使用するか、searchable (検索可能な) プロパティを false に設定します。
    リモート仮想化 リモート仮想化の使用時に検索が正しく動作しません。
    セル テキストが切れる問題 セル内のテキストが長すぎるために検索テキストが省略記号によって切れている場合も、セルまでスクロールして一致カウントに含まれますが、ハイライト表示はされません。

    API リファレンス

    このトピックでは、IgrTreeGrid にカスタム検索バーを実装し、更に検索結果を移動する際の機能を追加しました。アイコン、チップ、入力などその他の Ignite UI for React も使用しています。以下は検索 API です。

    IgrTreeGrid メソッド:

    IgrColumn プロパティ:

    その他のコンポーネント (またはそのいずれか) で使用した API:

    その他のリソース

    コミュニティに参加して新しいアイデアをご提案ください。