Предположим, есть два источника данных:
1) /messages — используется для отображения списка сообщений, возвращает только два поля
2) /message/{номер сообщения} — используется для детального отображения сообщения, возвращает все три поля
Каждый источник возвращает немного разные наборы данных. Первый источник возвращает, допустим, два поля, тогда как второй детальный источник дополнительно к первым двум полям возвращает еще одно поле.
Возникает вопрос, каким образом в этом случае лучше реализовать CRUD на ExtJS 4?
Для работы со списком сообщений нужна обычная модель и хранилище:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Ext.define('Messages.Model', { extend: 'Ext.data.Model', fields: [{ name: 'fid', type: 'int', useNull: true }, 'fssubject'] }); var storeMessages = Ext.create('Ext.data.Store', { autoLoad: true, autoSync: true, model: 'Messages', proxy: { type: 'rest', url: '/messages', reader: { type: 'json', root: 'data' }, writer: { type: 'json' } } }); |
Для работы с одной записью достаточно только одной модели:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Ext.define('Message.Model', { extend: 'Ext.data.Model', fields: [{ name: 'fid', type: 'int', useNull: true }, 'fssubject', 'fsbody'], proxy: { type: 'rest', url: '/message', reader: { type: 'json', root: 'data' }, writer: { type: 'json' } } }); |
Таким образом, для того чтобы из списка выбрать модель для детального просмотра и редактирования надо загрузить новую модель с конкретным идентификатором messageId:
1 2 3 4 5 |
Ext.ClassManager.get('Message.Model').load(messageId, { failure: this.onMessageLoadFailure, success: this.onMessageLoadSuccess, scope: this }); |
И связать ее с формой при успешной загрузке:
1 2 3 |
onMessageLoadSuccess: function(record, operation) { form.getForm().loadRecord(record); } |
Для удобства работы с формой создадим отдельный класс-наследник от стандартного класса формы:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
Ext.define('Ext.ux.form.Panel', { extend: 'Ext.form.Panel', /** * Can be a reference to a model instance or a model class name. */ model: null, /** * Set to the id of the model instance and the model will be loaded for you. * Only applicable if model provided is a model class name (string). */ modelId: null, loadMask: true, initComponent: function() { this.callParent(); this.getForm().trackResetOnLoad = true; //Workaround this.bindModel(this.model, this.modelId); this.addEvents('loadsuccess', 'loadfailure', 'savesuccess', 'savefailure'); }, bindModel: function(model, modelId) { if (Ext.isString(model)) { //Load a model to be updated if (modelId) { this.model = Ext.ClassManager.get(model); this.modelId = modelId; this.setLoading(this.loadMask); this.model.load(modelId, { success: this.onModelLoadSuccess, failure: this.onModelLoadFailure, scope: this }); //Load an empty record to be inserted } else { this.model = Ext.create(model, {}); this.loadRecord(this.model); } } else if (Ext.isObject(model)) { this.model = model; //Bind the provided model to be updated this.loadRecord(model); } }, commit: function(callback, scope) { if (this.form.isDirty()) { this.form.updateRecord(this.getRecord()); this.model.save({ callback: function(records, operation) { if (operation.wasSuccessful()) { this.fireEvent('savesuccess', this, records, operation); } else { this.fireEvent('savefailure', this, records, operation); } if (callback) { callback.call(scope || this, this, operation.wasSuccessful(), this.model); } }, scope: this }); } }, onModelLoadSuccess: function(record, operation) { this.model = record; this.loadRecord(record); this.fireEvent('loadsuccess', this, record, operation); this.setLoading(false); }, onModelLoadFailure: function(record, operation) { this.fireEvent('loadfailure', this, record, operation); this.setLoading(false); } }); |
Теперь нам достаточно создать форму и передать в нее имя модели и идентификатор или вызвать метод bindModel, форма сама загрузит модель и её данные.
1 2 3 4 5 6 7 8 9 10 11 |
// Create empty record Ext.create('Ext.ux.form.Panel', { model: 'Message.Model' }); //Modify an existing record for which you only have the id Ext.create('Ext.ux.form.Panel', { model: 'Message.Model', modelId: 1234 }); // Bind to exist form form.bindModel('Message.Model', 1234); |
Полностью рабочий пример доступен по ссылке: http://jsfiddle.net/elganz/fgfux