フックと機能による反応データグリッドのカスタマイズ



AGのグリッドは、カスタムコンポーネントを作成することによって広範なカスタマイズを可能にします.このポストでは、セルをレンダリングし、列の値をフィルタリングし、セルの値を編集するために、対応するデータグリッド用のカスタムコンポーネントを作成します.
これの以前のバージョンpost covers the same content with examples using classes . このポストでは、すべてのコード例は機能を使用して書かれて、フックを反応させます.
  • Video
  • Custom Components
  • Code and Getting Started
  • Start Point
  • Cell Renderer
  • Creating a Cell Editor
  • Custom Filter
  • Next Steps
  • ビデオ


    カスタムコンポーネント


    ビルドします.
  • 通貨記号で完全な通貨として数を表示するセルレンダリング.35000 なる€35,000.00 .
  • 入力キーを数字のみに制限するカスタムエディタ.
  • 値の範囲を選択するために構文を使用するフィルタ.30000 - 36000 .
  • コードと開始


    この例のコードはReact-Data-Grid ギタブのレポcustomization-demo-hooks フォルダ.
    あなたが開始する良い場所に反応を使用してAgグリッドを開始する場合はGetting Started in 5 Minutes with React Data Grid and Hooks 我々のドキュメンテーションに続くブログ柱Getting Started Guide .

    スタートポイント


    最初の出発点は以下の通りでしたCustomizedGrid.js :
    export function CustomGrid() {
    
        const [rowData, setRowData] = useState([]);
    
        const [colDefs, setColDefs] = useState(
            [
                {field:"make"},
                {field:"model"},
                {field:"price", editable:true}
            ]);
    
        useEffect(() => {
            fetch('https://www.ag-grid.com/example-assets/row-data.json')
                .then(result => result.json())
                .then(rowData => setRowData(rowData))
        }, []);
    
        return (
            <div className="ag-theme-alpine"
                style={{height: '400px', width: '600px'}}
            >
                <AgGridReact
                    defaultColDef={{sortable: true, filter: true }}
                    pagination={true}
                    rowData={rowData}
                    columnDefs={colDefs}>
                </AgGridReact>
            </div>
        );
    }
    
    
    これはグリッドをレンダリングし、サーバーからデータを読み込みます.
    CustomGridコンポーネントはApp.js 直接:
    import logo from './logo.svg';
    import './App.css';
    import {CustomGrid} from './CustomizedGrid.js'
    
    function App() {
      return (
        <CustomGrid />
      );
    }
    
    export default App;
    
    

    セルレンダラ


    最も単純なコンポーネントは、NumberFormatter.js :
    import React, { Component } from 'react';
    
    export function NumberFormatter(props){
    
            const value = Number(props.value);
            const text = value.toLocaleString(undefined, {style: 'currency', currency: 'EUR'});
    
            return (
                <span>{text}</span>
            );    
    }
    
    
    これは小道具を持っている機能であり、これらはComponent Cell Renderer ページ.
    ' value 'はセル内でレンダリングされる現在の値です.
    このコンポーネントですべてを変換するvalue からprops 数とそれから我々が我々の中で返す通貨にspan .
    これにより、次のように反応データグリッドに値が表示されます.

    セルレンダラの使用


    セルレンダラをグリッドコンポーネントで使用するには、次の手順に従います.
  • インポートします.
  • 列定義に追加します.
  • グリッドの定義frameworkComponents .
  • 通常通りにインポートします.
    import { NumberFormatter } from './NumberFormatter.js';
    
    
    列定義オブジェクトに追加します.この場合、price カラム.
                {field:"price", editable:true,
                cellRenderer: "numberFormatter",
                }
    
    
    次に、グリッド定義jsxに新しい属性を追加します.
                frameworkComponents={{
                    numberFormatter: NumberFormatter,
                }} 
    
    
    グリッドは、通貨記号でユーロで価格をレンダリングする必要があります.

    セルエディタの作成


    次のコンポーネントは、カスタムセルエディタです.
    細胞エディタは、公式ドキュメンテーションで文書化されますReact Data Grid Cell Editors .
    このセルエディタは単純ですinput キーを数値のみに制限するフィールド.値は、状態に格納され、編集された値が変更されたときにグリッドに格納されます.
    セルエディタの基本的な構造は以下の通りです.
    import React, {forwardRef, useState, useRef, useEffect, useCallback, useImperativeHandle} from 'react';
    
    export const NumericCellEditor = forwardRef((props, ref) => {
    
        const [value, setValue] = useState(parseInt(props.value));
        const refInput = useRef(null);
    
        return (
            <input 
                onKeyPress={onKeyPressListener}
                value={value}
                onChange={onChangeListener}
                ref={refInput} 
            />
        );  
    });
    
    
    上のコードはICellEditorParams ASprops に定義されているdocumentation , と要素へのref.
    最初にpropsから値の状態を設定します.
    上のコードにはonPressKeyListener the onChangeListener そしてフックuseImperativeHandle グリッドを使用してフォーカスを処理します.
    入力にフォーカスを設定する必要がありますafterGuiAttached しかし、我々はuseEffect フック
        // afterGuiAttached
        useEffect( ()=> refInput.current.focus(), []);
    
    
    The onChangeListener レンダリングに最適化するコールバックを使用して値を状態として修正します.
        const onChangeListener = useCallback( event => setValue(event.target.value), []);
    
    
    The onKeyPressListener , 再びuseCallback フック.これは、数字を入力することができますので、非数値キーを押すと、それを使用してevent.preventDefault() キープレスを無視する.
        const onKeyPressListener = useCallback( event => {
            if (!isNumeric(event.nativeEvent)) {
                event.preventDefault();
            }
    
            function isNumeric(event) {
                return /\d/.test(event.key);
            }
        }, []);
    
    
    コードの最後のチャンクはグリッドが値を受け取るのを許容することですuseImperativeHandle フック.
        useImperativeHandle(ref, () => {
            return {
                // the final value to send to the grid, on completion of editing
                getValue() {
                    return value;
                }
            };
        });
    
    
    コードの最終セットを与える
    import React, {forwardRef, useState, useRef, useEffect, useCallback, useImperativeHandle} from 'react';
    
    export const NumericCellEditor = forwardRef((props, ref) => {
    
        const [value, setValue] = useState(parseInt(props.value));
        const refInput = useRef(null);
    
        useImperativeHandle(ref, () => {
            return {
                getValue() {
                    return value;
                }
            };
        });
    
        const onKeyPressListener = useCallback( event => {
            if (!isNumeric(event.nativeEvent)) {
                event.preventDefault();
            }
    
            function isNumeric(event) {
                return /\d/.test(event.key);
            }
        }, []);
    
        const onChangeListener = useCallback( event => setValue(event.target.value), []);
    
        useEffect( ()=> refInput.current.focus(), []);
    
        return (
            <input 
                onKeyPress={onKeyPressListener}
                value={value}
                onChange={onChangeListener}
                ref={refInput} 
            />
        );  
    });
    
    
    これはテキスト入力フィールドとしてレンダリングされます:

    エディタでのグリッドの使用


    エディタを使用するには、「インポート」、「列」「def」に追加し、「フレームワーク」コンポーネントを定義します.
    import {NumericCellEditor} from './NumericCellEditor.js';
    
    
    列定義を追加します
        {field:"price",editable:true,
        cellRenderer: "numberFormatter",
        cellEditor: "numericCellEditor",
        }
    
    
    「フレームワーク」コンポーネントの定義を展開します
        frameworkComponents={{
            numberFormatter: NumberFormatter,
            numericCellEditor: NumericCellEditor,
        }} 
    
    
    エディタを使用すると、カスタム入力要素が使用されます.

    カスタムフィルタ


    カスタムフィルタは、書式を使用する入力になりますlow - high 例えば30000 - 35000 30000ユーロと35000ユーロの間だけの値を表示します.
    カスタムフィルタはRangeFilter.js .
    カスタムフィルタは、公式ドキュメントで文書化されますReact Data Grid Filter Component
    フィルタ構成要素の基本的な構造は以下の通りである.
    import React, { useState, forwardRef, useRef, useImperativeHandle, setState, useCallback, useEffect } from 'react';
    
    export const RangeFilter = forwardRef((props, ref) => {
    
        const [filter, setFilter] = useState('');
        const input = useRef(null);
    
        return (
            <form onSubmit={onSubmit}>
                <input name="filter" ref={input} defaultValue={filter}/>
                <button>Apply</button>
            </form>
        );
    
    });
    
    
    我々はフックを追加する必要がありますuseImperativeHandle グリッドと統合するには、フィルタを変更したコールバックを呼び出し、入力用のフォームを処理します.
    最初にフォーカスを入力に設定します.
        useEffect( ()=> input.current.focus(), []);
    
    
    そして、フィルタが変更されたときに、props :
        useEffect(() => {
            props.filterChangedCallback()
        }, [filter]);
    
    
    入力のDOMコンポーネントとしてフォームを使用しているので、onSubmit イベントが、既定のフォーム処理を防止し、フィルタ値を設定する状態を使用します.
        const onSubmit = useCallback( event => {
            event.preventDefault();
    
            let currFilter = event.target.elements.filter.value;
    
            if (filter !== currFilter) {
                setFilter( currFilter);
            }
        });
    
    
    次に、グリッドのライフサイクルコールバックを処理します.フィルタ自体はdoesFilterPass :
        useImperativeHandle(ref, () => {
            return {
                isFilterActive() {
                    return filter !== '';
                },
    
                doesFilterPass(params) {
                    const myfilter = filter.split('-');
    
                    const gt = Number(myfilter[0]);
                    const lt = Number(myfilter[1]);
                    const value = params.node.data.price;
    
                    return value >= gt && value <= lt;
                },
    
                getModel() {
                    return {filter: filter};
                },
    
                setModel(model) {
                    const filter = model ? model.filter : '';
                    setState( filter);
                }
    
            };
        });
    
    

    フィルタコンポーネントの使用


    以前と同じパターンを使用する:インポート、列のdefに追加し、フレームワークコンポーネントで定義します.
    import { RangeFilter } from './RangeFilter';
    
    
    列定義を追加します
        {field:"price",editable:true,
        cellRenderer: "numberFormatter",
        cellEditor: "numericCellEditor",
        filter: 'rangeFilter'
        }
    
    
    「フレームワーク」コンポーネントの定義を展開します
        frameworkComponents={{
            numberFormatter: NumberFormatter,
            numericCellEditor: NumericCellEditor,
            rangeFilter: RangeFilter
        }} 
    
    
    エディタが起動されると、カスタム入力要素が使用されます.

    次の手順


    この例の完全なコードは[反応データグリッド]にありますhttps://github.com/ag-grid/react-data-grid ] 例レポ.
    また、[データグリッドの例]ではいくつかの例がありますhttps://blog.ag-grid.com/react-data-grid-example-projects/ ] レポ.
    またはGetting Started ドキュメントのガイド.