#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;
}
このうち、getGuiとrefreshは必須。
また、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インターフェースのinitとgetGuiに相当?)
引数はinit呼び出し時と同じparams、また、HTML文字列またはDOMオブジェクトを返却する。
refreshやdestroyを実装する必要がなければ使うべし。
※ただし、ReactやAngularでは対応してない模様。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も不要。これはVueJSのtemplateに相当するため。
###VueJSでCheckBoxのCellRendererを実装する
ChechBoxのサンプルがなかったのでやってみました。
<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>
<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>
使用例。
this.columnDefs = [
{
headerName: 'Flag',
field: 'flag',
headerComponent: "checkboxColumn",
headerComponentParams : {readonly: true},
cellRenderer: "checkboxCell",
cellRendererParams :{readonly: true}
}
]
以上。