【问题标题】:ReactJS: AG-GRID: Dynamically Assigning Cell Editor based on metadataReactJS:AG-GRID:基于元数据动态分配单元格编辑器
【发布时间】: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


    【解决方案1】:

    我只是在寻找类似的东西,ag-grid 文档讨论了这个内置功能。 请参阅 ag-grid 文档 (v22.0.0) 中的“许多编辑一栏”部分:https://www.ag-grid.com/javascript-grid-cell-editing/#many-editors-one-column

    一栏多编辑

    也可以对同一列中的不同行使用不同的编辑器。通常,应用程序可能会检查行内容并相应地选择编辑器。将此 set colDef.cellEditorSelector 配置为一个函数,该函数返回要用作编辑器的组件的名称以及可选的要传递给它的自定义参数

    传递给此函数的参数与传递给单元格编辑器的参数相同..

    以下示例说明了如何在同一列中使用不同的编辑器和参数。请注意:

    • “值”列包含不同类型的数据,如“类型”列所示(数字/性别/情绪)。
    • colDef.cellEditorSelector 是一个函数,它根据该行的数据类型返回用于编辑的组件的名称
    cellEditorSelector:function (params) {
    
      if (params.data.type === 'age') return {
          component: 'numericCellEditor'
      };
    
      if (params.data.type === 'gender') return {
          component: 'agRichSelect',
          params: {values: ['Male', 'Female']}
      };
    
      if (params.data.type === 'mood') return {
          component: 'agRichSelect'
      };
    
      return null;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-14
      • 2016-10-31
      • 2019-08-09
      • 2019-01-10
      • 2020-02-19
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多