ag-grid使っていてやってみたこともろもろのメモです。
編集要素を持ったセルコンポーネントのエディタ切り替えを不可にする
と言うとわかりずらいですが、
- 例えばセルの表示状態(RendererComponent)をチェックボックスにしているときなど、カラム定義(ColumnDefs)のeditable:trueにしていると、ダブルクリックなどでinput要素に切り替わりカッコ悪くなる。
- それを回避しようと、該当するRendererを使うときは常にeditable:falseにして、そのうえでRendererParamsにreadonlyプロパティなどを勝手に渡して活性制御を行っていたのですが、そのうち、今度は行ごとに活性制御を行いたくなってきた。
- そうなると、やはりカラム定義のeditableには本来の用途で柔軟性をもたせたい。
で、EditorConponentへの切り替え自体をキャンセルさせてしまおう。と思いました。
UneditableEditor.vue
<template>
<div>dammy template</div>
</template>
<script>
import Vue from "vue";
export default Vue.extend({
methods: {
isCancelBeforeStart() {
return true;
},
},
})
</script>
つまり、編集不可能なEditorを設定する。
チェックボックスセルでは以下のようにeditableプロパティを使用できる。
ComboBoxCell.vue
<template>
<div>
<input type="checkbox"
v-model="isChecked"
@change="onChange"
:disabled="isDisabled"
>
</div>
</template>
<script>
import Vue from "vue";
export default Vue.extend({
data() {
return {
isChecked: false,
isDisabled: false
}
},
methods:{
onChange(){
this.params.setValue(this.isChecked);
this.params.api.refreshHeader();
},
},
mounted(){
let isChecked = true;
this.isChecked = this.params.value;
if(typeof(this.params.colDef.editable) === 'function'){
this.isDisabled = !this.params.colDef.editable(this.params)
}else{
this.isDisabled = !this.params.colDef.editable
}
}
})
</script>
ついでにヘッダーも。
CheckBoxColumn.vue
<template>
<div>
<input
:id="'id_'+params.column.colDef.field"
type="checkbox"
v-model="isChecked"
@change="onChange">
<label :for="'id_'+params.column.colDef.field">
{{ params.displayName }}
</label>
</div>
</template>
<script>
import Vue from "vue";
export default Vue.extend({
data() {
return {
isChecked: false
}
},
methods:{
onChange(){
this.params.api.forEachNode(node =>{
if(this.isEditable(node)){
node.setDataValue(this.params.column.colId, this.isChecked);
}
});
this.params.api.redrawRows();
},
updateCheckBoxCol(){
let isChecked = true;
this.params.api.forEachNode(node => {
if(this.isEditable(node) &&
!node.data[this.params.column.colId]) {
isChecked = false;
}
});
this.isChecked = isChecked;
},
/***
* checkboxセルの編集可否を判定
* colDefのeditableプロパティが関数の場合、RowNodeを与えて呼び出し。
* (引数のオブジェクトはdataプロパティを持っていることを前提)
* Params
* ------
* node: RowNode
*/
isEditable(node){
if(typeof(this.params.column.colDef.editable) === "function"){
return this.params.column.colDef.editable(node)
}
return this.params.column.colDef.editable
}
},
beforeUpdate(){
this.updateCheckBoxCol();
},
mounted(){
this.updateCheckBoxCol();
},
})
</script>
セルの入力状態(バリデーション)を管理する
以下、公式ドキュメントのソースをバリデーション用に修正。
<template>
<div>
<input
:ref="'input'"
v-model="value"
:maxlength="maxlength"
/>
</div>
</template>
<script>
import Vue from "vue";
export default Vue.extend({
data() {
return {
value: '',
cancelBeforeStart: false,
maxlength: 255
}
},
methods: {
getValue() {
/* 多分セルの編集完了時に呼び出されるだろうgetValueメソッド内で
バリデーションを実施。不正な入力が行われたセルのインデックスを
paramsのcontextプロパティに設定。 */
if(this.params.pattern){
let isValid = new RegExp(this.params.pattern).test(this.value)
// 当該セルをinvalidCellsリストから除外。
this.params.context.invalidCells = this.params.context.invalidCells.filter(
c => c[this.params.column.colId] !== this.params.rowIndex)
if(!isValid){
// 不正入力の場合は該当するセルのcolId:RowIndexのオブジェクトを設定。
const invalidCell = {}
invalidCell[this.params.column.colId] = this.params.rowIndex
this.params.context.invalidCells.push(invalidCell)
}
}
return this.value;
},
getCharCodeFromEvent(event) {
event = event || window.event;
return (typeof event.which === "undefined") ? event.keyCode : event.which;
},
},
created() {
this.value = this.params.value;
this.maxlength = this.params.maxlength
},
mounted() {
Vue.nextTick(() => {
if (this.$refs.input) {
this.$refs.input.focus();
}
});
}
})
</script>
例えば、上の情報をセルのスタイルなどに使用する。
this.gridOptions = {
context:{
invalidCells:[]
},
defaultColDef:{
cellClassRules: {
'invalid-input-cell': function(params) {
return params.context.invalidCells.find(c => c[params.colDef.field] === params.rowIndex)
},
}
},
(ちなみに)
javascript慣れてないです。
また、ag-gridのAPIにもっといい機能がすでにあるかもなので、ご指摘・情報あれば教えていただきたく。