Extjs4 Extjs 4 CRUD服务器端验证
我有这个商店定义,我想在带有编辑器插件的网格中使用它:Extjs4 Extjs 4 CRUD服务器端验证,extjs4,Extjs4,我有这个商店定义,我想在带有编辑器插件的网格中使用它: Ext.define('Workshop.store.WorkType', { extend: 'Ext.data.Store', model: 'Workshop.model.WorkType', autoLoad: true, autoSync: true, pageSize: 25, proxy: { type: 'ajax', api:
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'
}
}
});
如果输入有效数据,一切正常,但如果服务器验证失败怎么办,
如何实现字段被标记且编辑器不关闭
这也可以用于插入新记录,如何验证新数据?我可以部分解决您的问题。我在proxy中创建了
validate
方法,该方法在保存之前验证数据。这并不容易,但最终还是成功了(至少部分成功)。它不是很漂亮,但要做到这一点真的很难。这应该是在保存时创建验证的良好入口点。代码如下
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'}
]
});
在代理中,您应该创建验证方法:
// 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
});
}
});
这是一个工作示例。下面是我为一个演示项目所做的一个快速修改:
下面是rowedit插件的侦听器哈希
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'
}
}
});
服务器应返回如下响应:
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']
}
}