Extjs 4 CRUD服务器端验证

时间:2011-10-30 16:31:25

标签: extjs4

Ext.define('Workshop.store.WorkType', 
{
    extend: 'Ext.data.Store',
    model: 'Workshop.model.WorkType',
    autoLoad: true,
    autoSync: true,
    pageSize: 25,
    proxy: 
    {
        type: 'ajax',
        api: 
        {
            read: '/ajax_js.php?func=WorkType::selectRow',
            update: '/ajax_js.php?func=WorkType::updateRow',
            create: '/ajax_js.php?func=WorkType::insertRow',
            destroy: '/ajax_js.php?func=WorkType::deleteRow'
        },
        reader: 
        {
            type: 'json',
            root: 'root',
            successProperty: 'success',
            totalProperty: 'totalCount'
        }
    }
});

我有这个商店定义,我想在带有编辑器插件的网格中使用它:

Ext.define('Ext.ux.EditorGrid', 
{   
    extend: 'Ext.grid.Panel',
    plugins: 
    [
        Ext.create('Ext.grid.plugin.RowEditing', 
        {
            clicksToEdit: 2
        })
    ],
    store: Ext.create('Workshop.store.WorkType'),
    border: false,
    columns: 
    [
        {header: trans.translate('WORKTYPENAME'),  dataIndex: 'name',  flex: 1, editor: 'textfield'},
        {header: trans.translate('FACTOR'),  dataIndex: 'factor',  flex: 1, editor: 'textfield'}
    ]
});

如果输入有效数据,一切正常,但如果服务器验证失败,该怎么办? 如何才能实现标记并且编辑器不会关闭?

这也可用于新的记录插入,如何验证新数据?

2 个答案:

答案 0 :(得分:2)

这是我为演示项目做的快速黑客攻击:

下面是rowedit插件的监听器哈希

listeners: {
  canceledit: function(editor, e, options) {
    if (e.record.phantom) {
      return e.grid.store.remove(e.record);
    }
  },
  edit: function(editor, e) {
    var ed, grid;
    ed = editor;
    grid = editor.cmp;
    grid.el.mask('Loading ...', 'x-loading');
    return e.record.save({
      success: function(record, operation) {
        return grid.el.unmask();
      },
      failure: function(record, operation) {
        grid.el.unmask();
        ed.startEdit(grid.store.indexOf(record), 0);
        return Ext.Object.each(operation.request.proxy.reader.jsonData.errors, function(field, errors) {
          return ed.editor.down("[name=" + field + "]").markInvalid(errors);
        });
      }
    });
  }
}

服务器应该返回这样的响应:

{
  success: false,
  errors: {
    field1: ['error message1'],
    field2: ['error message2', 'error message3']
  }
}

答案 1 :(得分:0)

我部分解决了你的问题。我在代理中创建了validate方法,在保存之前验证数据。这并不容易,但最终它起作用(至少部分地)。它不是很漂亮,但要让这项工作变得非常困难。这应该是在保存时创建验证的良好入口点。代码如下。

// extended RowEditor
Ext.define('Ext.grid.ExtRowEditor', {
    extend: 'Ext.grid.RowEditor',

    // here we can plugin into editor
    onFieldAdd: function(map, fieldId, column) {
        this.callParent(arguments);

        var plugin = this.editingPlugin;
        var editor = column.getEditor();

        // if not yet initialized
        if (editor._extRowEditorInit === undefined) {

            // create interceptor to fire event that will eventually send validation request to the server
            editor.validate = Ext.Function.createInterceptor(editor.validate, function() {
                this.fireEvent('validationneeded', this, column, plugin);
            }, editor);

            // create validator
            editor.validator = function() {
                if (!this.errorValue) {
                    return true;
                }
                if (!this.getValue()) {
                    return true;
                }
                return (this.errorValue.toString() == this.getValue().toString()) ? this.errorMessage : true;
            };

            // create validationneeded event handler
            editor.on('validationneeded', this.onValidationneeded, this, { buffer: 100 });

            // mark initialized
            editor._extRowEditorInit = true;
        }
    },

    // send request to server
    onValidationneeded: function(editor, column, plugin) {
        var context = plugin.context;
        var store = context.store;
        var record = context.record;

        // if nothing changed we don't need to send request
        if (record.get(column.dataIndex) === editor.getValue()) {
            return;
        }

        // copy record; at this point original record still has old value, so we must set this from editor
        record = new record.store.model(record.data);
        record.set(column.dataIndex, editor.getValue());

        // create operation
        var operation = Ext.create('Ext.data.Operation', {
            action : 'validate',
            records: [
                record
            ]
        });
        var scope = { editor: editor, plugin: plugin };

        // create handler on exception; there is no way to access exception data from regular doRequest handler
        store.proxy.on('exception', function(sender, response, operation, opts) {
            // assign error to scope
            this.error = Ext.decode(response.responseText);
        }, scope, { single: true });

        // do request
        return store.proxy.doRequest(operation, this.onProxyValidate, scope);
    },

    // doRequest callback
    onProxyValidate: function(operation) {
        if (operation.action !== "validate") {
            return;
        }

        // if validation was successful then there is nothing to do
        if (this.error == undefined || this.error.success) {
            return;
        }

        var errors = this.error.errors;
        var plugin = this.plugin;
        var grid = plugin.grid;

        // this is private member
        var columns = grid.headerCt.getGridColumns();

        Ext.each(operation.records, function(record){
            Ext.each(errors, function(error) {
                // search column by dataIndex
                var column = Ext.Array.filter(columns, function(c) { return c.dataIndex == error.dataIndex; })[0];

                // get editor
                var editor = column.getEditor();

                // check if value in editor is still the same
                if (editor.getValue().toString() == record.get(column.dataIndex).toString()) {
                    // set properties on editor, which will be accessed from validator method
                    editor.errorValue = editor.getValue();
                    editor.errorMessage = error.message;
                    // editor.setActiveError(error.message);
                }
            });
        }, this);
        plugin.editor.onFieldChange();
    }
});

// Extended plugin; only difference is that it creates ExtRowEditor instead of RowEditor
Ext.define('Ext.grid.plugin.ExtRowEditing', {
    extend: 'Ext.grid.plugin.RowEditing',
    initEditor: function() {
        var me = this,
            grid = me.grid,
            view = me.view,
            headerCt = grid.headerCt;

        return Ext.create('Ext.grid.ExtRowEditor', {
            autoCancel: me.autoCancel,
            errorSummary: me.errorSummary,
            fields: headerCt.getGridColumns(),
            hidden: true,

            // keep a reference..
            editingPlugin: me,
            renderTo: view.el
        });
    }
});

在代理中,您应该创建validation方法:

var store = Ext.create('Ext.data.Store', {
    proxy: {
        type: 'ajax',
        api: 
        {
            read: 'api/read.php',
            update: 'api/update.php',
            create: 'api/create.php',
            destroy: 'api/destroy.php',
            validate: 'api/validate.php' // validation method
        },
        reader: {
            type: 'json',
            root: 'data'
        }
    }
});

Here正在制作样本。