【问题标题】:Form with textfield and grid: send all values to the server带有文本字段和网格的表单:将所有值发送到服务器
【发布时间】:2018-04-21 17:26:01
【问题描述】:

在创建和更新表单时,有时需要让用户能够动态地将字段添加到相同类型的值(多个电话、多个地址等)。

我正在探索几种可能性。

其中之一是将网格用作表单域。

但是,我对如何最好地实现这个想法存有疑问,尤其是如何将所有表单字段值(文本字段和网格)发送到服务器(以及稍后如何在表单中加载它们以进行编辑)。

摆弄一些想法:

一个带有单元格编辑插件https://fiddle.sencha.com/#view/editor&fiddle/2ftp

另一个使用 rowediting gplugin 的 https://fiddle.sencha.com/#view/editor&fiddle/2fto

【问题讨论】:

  • 为什么不在每个电话字段旁边放置一个“添加”按钮并在按下时插入另一个电话字段?表单发送里面的所有字段。此外,在表单加载时插入多个电话字段以进行编辑也很简单。
  • @abeyaz 有时需要多组字段,在这种情况下,最好选择网格组件的巨大潜力。感谢您的想法

标签: extjs extjs5


【解决方案1】:

不确定“最佳实施”,但我已经看到了多值输入的许多要求,为了可重用性,我在我的工具箱中有一个类似于以下的网格字段:

Ext.define('Ext.ux.GridField', {
    extend: 'Ext.form.FieldContainer',
    alias: 'widget.gridfield',
    initComponent: function () {
        var me = this;
        if(!me.columns) me.columns = {
             dataIndex: 'field1'
        };
        if(!me.mapFn) me.mapFn = function(value) {
            if(Ext.isObject(value)) return value;
            return {
                field1: value
            };
        };
        if(!me.unmapFn) me.unmapFn = function(record) {
            return record.get('field1');
        };
        me.grid = Ext.widget(Ext.apply({
            xtype: 'grid',
            viewConfig: {
                markDirty: false
            },
            store: me.store || Ext.create('Ext.data.Store', {
                fields: me.columns.map(function(column) {
                    return {
                        name: column.dataIndex,
                        type: column.dataType || 'auto',
                        defaultValue: column.defaultValue
                    };
                }),
                listeners: {
                    update: me.updateValue,
                    datachanged: me.updateValue,
                    scope: me
                }
            }),
            columns: [{
                xtype: 'actioncolumn',
                getClass: function () {
                    return 'x-fa fa-times'
                },
                handler: function(grid, rowIndex, colIndex, item, e, record) {
                    grid.getStore().remove(record);
                },
                width: 35
            }].concat(me.columns),
            bbar: [{
                xtype: 'button',
                iconCls: 'x-fa fa-pencil',
                text: 'Add',
                handler: function(btn) {
                    var grid = btn.up('grid'),
                        store = grid.getStore(),
                        record = store.add(Ext.clone(me.emptyRecord) || {})[0];
                    grid.getPlugin('editor').startEditByPosition({
                        row: store.indexOf(record),
                        column: 1
                    });
                }
            }],
            plugins: [
                Ext.create('Ext.grid.plugin.CellEditing', {
                    pluginId: 'editor',
                    clicksToEdit: 1
                })
            ]
        }, me.gridConfig)); // "gridConfig" config can override everything on each instance.
        me.hiddenField = Ext.widget({
            xtype: 'hiddenfield',
            name: me.name,
            value: '',
            allowNull: false,
            rawToValue: function (raw) {
                return raw;
            },
            valueToRaw: function (value) {
                return value;
            },
            getRawValue: function () {
                return Ext.valueFrom(this.rawValue, '')
            },
            isEqual: function (a, b) {
                return Ext.encode(a) == Ext.encode(b)
            },
            listeners: {
                change: function(field, nV, oV) {
                    if(!Ext.isArray(nV)) nV = [nV];
                    var store = me.grid.getStore();
                    store.removeAll();
                    store.add(nV.map(me.mapFn));
                }
            }
        });
        Ext.apply(me, {
            layout: 'fit',
            items: [{
                xtype:'container',
                border: 1,
                style: {
                    borderColor: '#d0d0d0',
                    borderStyle: 'solid'
                },
                items: [me.grid]
            }, me.hiddenField]
        });
        me.callParent(arguments);
    },
    updateValue: function() {
        var me = this,
            grid = me.grid,
            hiddenField = me.hiddenField,
            nV = grid.getStore().getRange().map(me.unmapFn, me),
            oV = me.hiddenField.getValue();
        if(!oV || Ext.isArray(oV) && Ext.encode(nV) != Ext.encode(oV)) {
            hiddenField.suspendCheckChange++;
            hiddenField.setValue(nV);
            hiddenField.suspendCheckChange--;
            me.fireEvent('change', me, nV, oV);
        }
    }
});

然后可以这样使用:

},{
    xtype: 'gridfield',
    fieldLabel: 'Contacts',
    name: 'contacts',
    columns: [{
        text: 'Type',
        dataIndex: 'type',
        editor:{
            xtype: 'combobox',
            name: 'type',
            valueField: 'name',
            displayField: 'name',
            store: combostore,
            queryMode: 'local'
        },
        flex: 0.7
    },{
        text: 'Description',
        dataIndex: 'description',
        editor:{
            xtype: 'textfield',
            name: 'description'
        },
        flex: 1
    }],
    mapFn: function(value) {
        return value;
    },
    unmapFn: function(record) {
        return record.getData();
    }
}, {

我根据您的小提琴为您制作了fiddle,包括表单上的工作负载和保存操作,但在 ExtJS 6.x 中。我有checked that it works with ExtJS 5 as well,虽然你必须添加工作图标。

【讨论】:

  • 谢谢亚历山大。一个很大的帮助(一如既往)。您的示例非常完整,对我有很大帮助。我喜欢这个解决方案。我将逐行研究(并尝试正确理解所有内容)。
  • Alexandre,该组件工作正常,但我在更新中有一个问题。我尝试使用单个查询(使用 PHP 和 MYSQL)在每一行中引入存储更新记录所需的所有数据,但我没有得到与网格字段(多值)所需的数据相关的数据。你怎么做到这一点?数据已经在商店中全部可用,或者当您选择要编辑的记录时,您通过发送该特定记录的 id 以将必要的数据过滤到网格字段来发出新请求?
猜你喜欢
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多