今回もag-Gridについて
任意のデータをコールバックで使いたいときに使える小ネタです
gridの一覧にデータを表示したときのデータを保持しておいてその値が変わったらスタイルを適用したいといった場合
- 環境
ag-grid:18.1.2 angular: 6.1.4

要件としては
- 数値が編集されたらスタイルを変更したい
- 初期値から変わった場合のみスタイルを変えたい
ということが実現したいわけですね
実装案1 cellValueCanged
ここで考えるのはまずcellValueCahgedのコールバックでゴニョゴニョできるかなと考えるかと思います
cellValueChangedでコールバックに渡ってくるデータはoldValue,newValueがあるので行けそうな気がします
しかし、このコールバックには直近の編集前後の値のみしか渡ってきません
- 特定セルの数値を100 -> 105
- 特定セルの数値を105 -> 100
といった操作をした場合にあたかも変更されたものとしてスタイルが適用されてしまいます
要件の2つ目が満たせないわけですね
実装案2 cellRendererFramework + Service
- CellRendererFrameworkを用いてコンポーネントから状態管理用のサービスを呼び出して判定を行う
具体的にはこんな感じでしょうか
- 初期状態のデータを持つサービスを用意
- 数値をレンダリングするだけのag-Grid用のカスタムコンポーネントを用意
- カスタムコンポーネント上でサービスを呼び出してセルの描画の際にスタイルを適用
ただスタイルを変えたいだけなのに。。。大げさすぎる気がしますね
実装案3 contextを使ってデータを参照する
そこでcontextの出番です
contextについてはこちら
ag-Grid Features: Context Object
- gridのデータを受け取った瞬間にcontextの中身を更新
- スタイルやクラスを決めるコールバック側ではcontextの中の値を使って変更がされているのか判断
これだけです
実際のコードはこんな感じ
- component.ts(一部抜粋)
import _ from 'lodash';
ngOnInit() {
this.gridOptions = <GridOptions>{};
this.columnDefs = [
.....
.....
.....
{
headerName: 'price',
field: 'price',
width: 100,
// contextに持っているデータと比較して変化がある場合はスタイルを適用させる
cellClassRules: {
'bg-danger': params => {
const nodeId = params.node.id;
const field = params.colDef.field;
return params.value != params.context.rowData[nodeId][field];
},
},
editable: true
}
];
this.rowData = [
{
price: 100
},
{
price: 200
}
];
// データがセットされた状態を保存
this.gridOptions.context = { rowData: _.cloneDeep(this.rowData) };
}
- component.html
<ag-grid-angular #sampleGrid
class="ag-theme-balham grid"
[gridOptions]="gridOptions"
[rowData]="rowData"
[columnDefs]="columnDefs"
(cellValueChanged)="valueChanged($event)">
</ag-grid-angular>
感想
contextにデータ入れとけば色んな所で使えるよっていう感じのあれです
グローバル変数的な感じですね
こういうのって便利便利で使っているとあっという間に肥大化してデバッグができなくなっていくので
- 基本参照のみにする
- コールバック内で書き換えを行わない
- 多用しない
- 他の手段で代替出来ないか調べる
など気をつける必要はありそうだなと思いました
ag-Gridのドキュメントは一応さらっと読んだのである程度何ができるか把握しているつもりだったのですが全然まだまだだったようです
結局必要にならないと真剣に調べられないんだろうなーとしみじみ感じましたがこれからも精進していく所存ですw