【发布时间】:2019-10-26 09:09:30
【问题描述】:
我希望根据元数据动态应用单元格编辑器。例如,如果该行被确定为数字(即保存整数数据的行),我想使用数字编辑器。对于日期、日期编辑器等...
我只会在运行时知道每一行的定义,因为每一行都可以保存自己的数据类型,如果编辑器是特定于数据类型的,则在列级别应用单元格编辑器将不起作用(I'我试图在列级别定义一个通用编辑器,但我觉得我没有足够的能力来实现它,我也没有足够的“真实”代码来展示一个例子)。
这是我的组件:
import React, { Component } from 'react';
import axios from 'axios';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-balham.css';
import NumericEditor from "./numericEditor.jsx";
import DatePicker from 'react-date-picker'
const API = 'http://localhost:53884/api/UserConfig/UI'
var PARMS = '';
class UserConfig extends Component {
constructor(props) {
super(props);
this.state = {
columnDefs: [],
components: null,
rowData: null,
isLoading: false,
error: null,
config: [],
heading: "",
meta: [],
frameworkComponents: {
numericEditor: NumericEditor,
datePicker: DatePicker
}
};
this.onGridReady = this.onGridReady.bind(this);
}
onGridReady(params) {
this.gridApi = params.api;
this.columnApi = params.columnApi;
this.gridApi.sizeColumnsToFit();
}
componentDidMount() {
this.setState({ isLoading: true });
axios.get(API + PARMS)
.then(fubar => {
const config = fubar.data.config;
const headerRow = fubar.data.header;
const rowData = fubar.data.results;
const meta = fubar.data.meta;
this.setState({ heading: "User Configuration: Trade Date " + new Date(config.tradeDate).toLocaleDateString("en-US") });
var newCols = [
{ headerName: "", field: "attribute", width: 200, hide: true },
{ headerName: "", field: "displayName", width: 200, resizable: true, sortable: true, filter: true },
{ headerName: headerRow.value0, field: "value0", width: 100, resizable: true, editable: true },
{ headerName: headerRow.value1, field: "value1", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value2, field: "value2", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value3, field: "value3", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value4, field: "value4", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value5, field: "value5", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value6, field: "value6", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value7, field: "value7", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value8, field: "value8", width: 100, resizable: true, editable: false },
{ headerName: headerRow.value9, field: "value9", width: 100, resizable: true, editable: false },
];
if (headerRow.value0 === null) newCols[2].hide = true;
if (headerRow.value1 === null) newCols[3].hide = true;
if (headerRow.value2 === null) newCols[4].hide = true;
if (headerRow.value3 === null) newCols[5].hide = true;
if (headerRow.value4 === null) newCols[6].hide = true;
if (headerRow.value5 === null) newCols[7].hide = true;
if (headerRow.value6 === null) newCols[8].hide = true;
if (headerRow.value7 === null) newCols[9].hide = true;
if (headerRow.value8 === null) newCols[10].hide = true;
if (headerRow.value9 === null) newCols[11].hide = true;
this.setState({ rowData, config, columnDefs: newCols, meta });
})
.catch(error => this.setState({
error,
isLoading: false
}));
}
onCellEditingStarted = params => {
const { meta } = this.state;
const attribute = params.data.attribute;
var cols = this.state.columnDefs;
const metaRow = meta.find(item => { return item.attribute === attribute });
if (metaRow.dataType === "datetime") cols[2].cellEditor = "datePicker";
if (metaRow.dataType === "int") cols[2].cellEditor = "numericEditor";
this.setState({ columnDefs: cols });
//NumericEditor(params);
//alert('Display Name = ' + metaRow.displayName + ',\n'
// + 'Display Order = ' + metaRow.displayOrder + ',\n'
// + 'Default Value = ' + metaRow.defaultValue + ',\n'
// + 'Data Type = ' + metaRow.dataType + ',\n'
// + 'Allow Nulls = ' + metaRow.allowNull);
};
render() {
const { heading, rowData, columnDefs } = this.state;
return (
<div className="ag-theme-balham" style={{ height: '500px', width: '800px' }} >
<h2 style={{ paddingLeft: '32px' }}>{heading}</h2>
<AgGridReact
columnDefs={columnDefs}
rowData={rowData}
onCellClicked={this.onCellClicked.bind(this)}
frameworkComponents={this.state.frameworkComponents}
/>
</div>
);
}
}
export default UserConfig;
我的方法是利用 onCellClicked:
<AgGridReact
columnDefs={columnDefs}
rowData={rowData}
onCellClicked={this.onCellClicked.bind(this)}
frameworkComponents={this.state.frameworkComponents}
/>
在下面的事件处理程序中应用单元格编辑器更改:
onCellClicked = params => {
const { meta } = this.state;
const attribute = params.data.attribute;
var cols = this.state.columnDefs;
const metaRow = meta.find(item => { return item.attribute === attribute });
if (metaRow.dataType === "datetime") cols[2].cellEditor = "datePicker";
if (metaRow.dataType === "int") cols[2].cellEditor = "numericEditor";
this.setState({ columnDefs: cols });
};
每次单击单元格时,都会确定单元格行的数据类型,并修改列 [2] 的单元格编辑器以反映单元格行数据类型。
对我来说,这是一种严厉的方法,但我不确定如何才能留在 ReactJS/AG-Grid 世界中。
顺便说一句,当有人能够点击一个单元格时,columnDefs 的状态已经设置了两次:点击一个单元格将代表第 3 次以上。
========== 编辑 ==========
我发现大幅改变 cols 结构会触发应用程序应用我的单元格编辑器更改。例如,当将我的 columnDefs 复制到一个新数组中时,我对少数列进行切片而不是获取整个数组:
var cols = this.state.columnDefs.slice(0,8);
当我设置列状态时,
this.setState({ columnDefs: cols });
我的编辑器选择开始了。
当然,我不想——也不需要——对我的列定义做出如此彻底的改变。如果我这样做了,我可能会考虑在每次有人单击一个单元格时添加一个新列,也许如果目标行数据类型与最后一次单击的数据类型不同。但这似乎是一个非常糟糕的方法。
我没有成功的另一种方法是使用以下任一方法强制更新:
this.forceUpdate();
this.setState({ state: this.state });
但在这里似乎都没有效果。
感谢您的反馈 - 谢谢。
【问题讨论】:
标签: reactjs editor ag-grid-react