Я хочу применить редактор ячеек динамически на основе метаданных. Например, если строка определена как числовая (то есть строка, содержащая целочисленные данные), я хочу использовать редактор чисел. Для Даты, Редактора Даты и т.д ...
Я буду знать только во время выполнения определение каждой строки, и поскольку каждая строка может содержать свой собственный тип данных, применение редактора ячеек на уровне столбца не будет работать, если редактор зависит от типа данных (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}
/>
для применения изменения Cell Editor в обработчике событий ниже:
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 заставит приложение применить изменения в Cell Editor. Например, при копировании моего columnDefs в новый массив, и я нарезаю несколько столбцов вместо того, чтобы взять весь массив:
var cols = this.state.columnDefs.slice(0,8);
когда я устанавливаю состояние столбца,
this.setState({ columnDefs: cols });
мой выбор редактора вступает в силу.
Конечно, я не хочу - и мне не нужно - вносить столь радикальные изменения в определения моих столбцов. Если бы я это сделал, я мог бы подумать о добавлении нового столбца каждый раз, когда кто-то щелкает по ячейке, возможно, если тип данных целевой строки не совпадает с последним нажатым. Но это кажется очень плохим подходом.
Другой подход, с которым у меня не получилось, - принудительно обновить, используя либо:
this.forceUpdate();
this.setState({ state: this.state });
но ни один из них не кажется здесь эффективным.
Я ценю ваши отзывы - спасибо.