В ExtJs 5 используется схема данных. Она определяется в базовом классе, от которого должны наследоваться все связанные модели. Связывание моделей стало удобнее, чем в предыдущей версии. Появилась возможность в описании поля указывать свойство reference.
Определим, например две модели с общей базой - модель сотрудников и модель департаментов:
Ext.define('MyApp.Base', {
extend: 'Ext.data.Model',
schema: {
namespace: 'MyApp.'
}
});
Ext.define('MyApp.Person', {
extend: 'MyApp.Base',
fields: [
{ name: 'id', type: 'int' },
{ name: 'personName', type: 'string' },
{
name: 'person',
reference: {
parent: 'Department',
inverse: 'persons'
}
}
]
});
Ext.define('MyApp.Department', {
extend: 'MyApp.Base',
fields: [
{ name: 'id', type: 'int' },
{ name: 'departmentName', type: 'string' }
],
proxy: { ... }
});
Если загрузить куст информации о конкретном департаменте, то зависимые модели создадутся автоматически.
MyApp.Department.load(1, {
scope: this,
params: {
cluster: true
},
success: function(department) {
console.log(department.persons()); <-- здесь получаем Store
}
});
Сервер отправил такой ответ:
{
success: true,
data: {
id: 1,
departmentName: 'Финансовый департамент',
persons:[
{ id: 34, personName: 'Иванов' },
{ id: 15, personName: 'Петров' }
]
}
}
Это очень удобно, однако можно столкнуться с одной проблемой. Когда нужно связать модели, используемые в обычных гридах и в деревьях, одну базу выбрать сложно, поскольку для гридов нужно наследоваться от Ext.data.Model, а для деревьев нужно наследоваться от Ext.data.TreeModel.Если попытаться указать параметр schema в двух моделях, то появляется сообщение об ошибке, в котором чёрным по белому написано, что так делать нельзя.
Выход - поступить как разработчики библиотеки, превращая Model в TreeModel.
Ext.define('MyApp.Base', {
extend: 'Ext.data.Model',
idProperty: 'id',
schema: {
namespace: 'MyApp.'
}
});
Ext.define('MyApp.TreeBase', { // see Ext.data.TreeModel source code
extend: 'MyApp.Base',
requires: [
'Ext.data.NodeInterface'
],
mixins: [
'Ext.mixin.Queryable'
],
getRefItems: function() {
return this.childNodes;
},
getRefOwner: function() {
return this.parentNode;
},
},
function () {
Ext.data.NodeInterface.decorate(this);
});
---------------------------------------
Ext.define('MyApp.Model', {
extend: 'MyApp.Base',
...
});
Ext.define('MyApp.TreeModel', {
extend: 'MyApp.TreeBase',
...
});
Теперь наследуем древовидные модели от MyApp.TreeModel, а табличные модели от MyApp.Model.
Засада. Если компания содержит структуру департаментов, то company.departments() вернёт обычное хранилище, а не древовидное, как можно было бы ожидать:
company.departments().isStore === true
company.departments().isTreeStore === undefined
Записи в этом хранилище поддерживают Ext.data.NodeInterface, поэтому не всё так ужасно.
Определим, например две модели с общей базой - модель сотрудников и модель департаментов:
Ext.define('MyApp.Base', {
extend: 'Ext.data.Model',
schema: {
namespace: 'MyApp.'
}
});
Ext.define('MyApp.Person', {
extend: 'MyApp.Base',
fields: [
{ name: 'id', type: 'int' },
{ name: 'personName', type: 'string' },
{
name: 'person',
reference: {
parent: 'Department',
inverse: 'persons'
}
}
]
});
Ext.define('MyApp.Department', {
extend: 'MyApp.Base',
fields: [
{ name: 'id', type: 'int' },
{ name: 'departmentName', type: 'string' }
],
proxy: { ... }
});
Если загрузить куст информации о конкретном департаменте, то зависимые модели создадутся автоматически.
MyApp.Department.load(1, {
scope: this,
params: {
cluster: true
},
success: function(department) {
console.log(department.persons()); <-- здесь получаем Store
}
});
Сервер отправил такой ответ:
{
success: true,
data: {
id: 1,
departmentName: 'Финансовый департамент',
persons:[
{ id: 34, personName: 'Иванов' },
{ id: 15, personName: 'Петров' }
]
}
}
Это очень удобно, однако можно столкнуться с одной проблемой. Когда нужно связать модели, используемые в обычных гридах и в деревьях, одну базу выбрать сложно, поскольку для гридов нужно наследоваться от Ext.data.Model, а для деревьев нужно наследоваться от Ext.data.TreeModel.Если попытаться указать параметр schema в двух моделях, то появляется сообщение об ошибке, в котором чёрным по белому написано, что так делать нельзя.
Выход - поступить как разработчики библиотеки, превращая Model в TreeModel.
Ext.define('MyApp.Base', {
extend: 'Ext.data.Model',
idProperty: 'id',
schema: {
namespace: 'MyApp.'
}
});
Ext.define('MyApp.TreeBase', { // see Ext.data.TreeModel source code
extend: 'MyApp.Base',
requires: [
'Ext.data.NodeInterface'
],
mixins: [
'Ext.mixin.Queryable'
],
getRefItems: function() {
return this.childNodes;
},
getRefOwner: function() {
return this.parentNode;
},
},
function () {
Ext.data.NodeInterface.decorate(this);
});
---------------------------------------
Ext.define('MyApp.Model', {
extend: 'MyApp.Base',
...
});
Ext.define('MyApp.TreeModel', {
extend: 'MyApp.TreeBase',
...
});
Теперь наследуем древовидные модели от MyApp.TreeModel, а табличные модели от MyApp.Model.
Засада. Если компания содержит структуру департаментов, то company.departments() вернёт обычное хранилище, а не древовидное, как можно было бы ожидать:
company.departments().isStore === true
company.departments().isTreeStore === undefined
Записи в этом хранилище поддерживают Ext.data.NodeInterface, поэтому не всё так ужасно.