3
3

More than 5 years have passed since last update.

Cell Renderer Components(ag-Grid)の作り方

Last updated at Posted at 2018-10-14

ag-GridでCell Renderer Componentsを作る

公式ドキュメントからのまとめ。
というかほぼそのまんま。VueJSが射程です。

Cell Renderer Componentsとは

セル描画のふるまいをカスタマイズするコンポーネント。

Cell Renderer Componentsのインターフェース

公式ドキュメントより

interface ICellRendererComp {
    // Optional - Params for rendering. The same params that are passed to the cellRenderer function.
    init?(params: ICellRendererParams): void;

    // Mandatory - Return the DOM element of the component, this is what the grid puts into the cell
    getGui(): HTMLElement;

    // Optional - Gets called once by grid after rendering is finished - if your renderer needs to do any cleanup,
    // do it here
    destroy?(): void;

    // Mandatory - Get the cell to refresh. Return true if the refresh succeeded, otherwise return false.
    // If you return false, the grid will remove the component from the DOM and create
    // a new component in it's place with the new values.
    refresh(params: any): boolean;
}

このうち、getGuirefreshは必須。
また、refresh以外はただ一度だけ呼ばれ、refreshは以下のタイミングで0~n回発生。

  • rowNode.setDataValue(colKey, value)の呼び出し時
  • セル編集時、セル編集完了時
  • api.refreshCells()の呼び出し時

ICellRendererParamsのインターフェース

公式ドキュメントより

interface ICellRendererParams {
    value: any, // value to be rendered
    valueFormatted: any, // value to be rendered formatted
    getValue: ()=> any, // convenience function to get most recent up to date value
    setValue: (value: any) => void, // convenience to set the value
    formatValue: (value: any) => any, // convenience to format a value using the columns formatter
    data: any, // the rows data
    node: RowNode, // row rows row node
    colDef: ColDef, // the cells column definition
    column: Column, // the cells column
    rowIndex: number, // the current index of the row (this changes after filter and sort)
    api: GridApi, // the grid API
    eGridCell: HTMLElement, // the grid's cell, a DOM div element
    eParentOfValue: HTMLElement, // the parent DOM item for the cell renderer, same as eGridCell unless using checkbox selection
    columnApi: ColumnApi, // grid column API
    context: any, // the grid's context
    refreshCell: ()=>void // convenience function to refresh the cell
}

Cell Renderer Componentに引数を渡す

cellRendererParamsを使う。

// define cellRenderer to be reused
var myCellRenderer = function(params) {
    return '<span style="color: '+params.color+'">' + params.value + '</span>';
}

// use with a color
colDef.cellRenderer = myCellRenderer;
colDef.cellRendererParams = {
    color: 'guinnessBlack'
}

// use with another color
colDef.cellRenderer = myCellRenderer;
colDef.cellRendererParams = {
    color: 'irishGreen'
}

コンポーネントの登録

ag-Gridコンポーネントの登録

Cell Renderer Function

コンポーネントを一から実装する代わりに、単純なファンクションだけでもよい。
(これはICellRendererCompインターフェースのinitgetGuiに相当?)
引数はinit呼び出し時と同じparams、また、HTML文字列またはDOMオブジェクトを返却する。
refreshdestroyを実装する必要がなければ使うべし。
※ただし、ReactAngularでは対応してない模様。VueJSではできた。
以下参考

// put the value in bold
colDef.cellRenderer = function(params) {
    return '<b>' + params.value.toUpperCase() + '</b>';
}

// put a tooltip on the value
colDef.cellRenderer = function(params) {
    return '<span title="the tooltip">'+params.value+'</span>';
}

// create a DOM object
colDef.cellRenderer = function(params) {
    var eDiv = document.createElement('div');
    eDiv.innerHTML = '<span class="my-css-class"><button class="btn-simple">Push Me</button></span>';
    var eButton = eDiv.querySelectorAll('.btn-simple')[0];

    eButton.addEventListener('click', function() {
        console.log('button was clicked!!');
    });

    return eDiv;
}

Cell Renderer Instanceにアクセスする

grid APIのgetCellRendererInstances(params)を使用する。以上。

シグネチャと引数のインターフェースです。

// function takes params to identify what cells and returns back a list of cell renderers
function getCellRendererInstances(params: GetCellRendererInstancesParams): ICellRendererComp[];

// params object for the above
interface GetCellRendererInstancesParams {
    // an optional list of row nodes
    rowNodes?: RowNode[];
    // an optional list of columns
    columns?: (string|Column)[];
}

使用例。

// example - get cell renderer for first row and column 'gold'
var firstRowNode = gridOptions.api.getDisplayedRowAtIndex(0);
var params = { columns: ['gold'], rowNodes: [firstRowNode]};
var instances = gridOptions.api.getCellRendererInstances(params);
if (instances.length > 0) {
    // got it, user must be scrolled so that it exists
    var instance = instances[0];
}

VueJSでCellRendererを実装する

以下の点で例外があるが、VueJSでもICellRendererインターフェースの実装が有効。

  • initは不要。セルの値はparamsと呼ばれるデータフィールドによって暗黙的に使用可能となっている?とのこと(this.paramsで値にアクセスできる)。
  • getGuiも不要。これはVueJStemplateに相当するため。

VueJSでCheckBoxのCellRendererを実装する

ChechBoxのサンプルがなかったのでやってみました。

CheckBoxCell.vue
<template>
    <div>
        <input type="checkbox" 
        :checked="isChecked"
        :disabled="isReadonly"
        @change="onChange"
        >
    </div>
</template>

<script>
import Vue from "vue";

export default Vue.extend({
    data() {
        return {
            isChecked: false,
            isReadonly: false
        }
    },
    methods:{
        /**
         * 更新が行われた際に、セルの値をチェック状態としてセットする。
         */
        refresh(){
            this.isChecked = this.params.getValue()
            return true
        },
        /**
         * changeイベント時にチェック状態をセルの値としてセットする。
         * セルのチェック状態に応じてヘッダーも更新したいため、
         * api.refreshHeader()を呼び出す。
         */
        onChange(){
            this.isChecked = !this.isChecked;
            this.params.setValue(this.isChecked);
            this.params.api.refreshHeader();
        },
    },
    /**
     * コンポーネントパラメータの受け取り。
     */
    beforeMount(){
        this.isChecked = this.params.value
        this.isReadonly = this.params.readonly
    }
})
</script>   

<style scoped>
    div{
        text-align: center;
    }
</style>
CheckBoxHeader.vue
<template>
    <div>
        <input 
        v-if="!isReadonly"
        type="checkbox" 
        :checked="isChecked"
        @change="onChange">
        <span>
        {{ params.displayName }}
        </span>
    </div>
</template>

<script>
import Vue from "vue";

export default Vue.extend({
    data() {
        return {
            isChecked: false,
            isReadonly: true
        }
    },
    methods:{
        /**
         * changeイベント時にチェック状態をセルの値に反映する。
         * setDataValueで値の設定を行うことで、
         * CellRendererコンポーネントのrefreshが呼ばれるはず。
         */
        onChange(){
            this.isChecked = !this.isChecked;
            let colId = this.params.column.colId;
            this.params.api.forEachNode(node =>{
                node.setDataValue(colId, this.isChecked);
            });
        },
        /**
         * ヘッダーの初期表示設定。
         */
        initHeader(){
            let isChecked = true;
            let colId = this.params.column.colId;
            this.params.api.forEachNode(node =>{
                if(!node.data[colId]){
                    isChecked = false;
                } 
            });
            this.isChecked = isChecked;
        }
    },
    /**
     * コンポーネントパラメータの受け取り。
     * 及び、ヘッダーの初期表示設定(DOMの更新を待ちうけるためnextTickを使用)。
     */
    beforeMount(){
        this.isReadonly = this.params.readonly
        Vue.nextTick(() => {
            this.initHeader();
        });
    }
})

</script>

使用例。

~.vue
            this.columnDefs = [
                {
                    headerName: 'Flag', 
                    field: 'flag',
                    headerComponent: "checkboxColumn",
                    headerComponentParams : {readonly: true},
                    cellRenderer: "checkboxCell",
                    cellRendererParams :{readonly: true}
                }
       ]

以上。

3
3
1

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
3