14.07.2014, 12:19
|
|
Профессор
|
|
Регистрация: 06.06.2014
Сообщений: 292
|
|
ExtJS5 - модель и схема
Здравствуйте.
Пытаюсь реализовать пример по работе с моделями и схемой. Нашел вот этот ресурс: http://www.sencha.com/products/extjs...s-data-package и начал пробовать. Базовая модель:
Ext.define("Communication.model.Base", {
extend: "Ext.data.Model"
,schema: {
namespace: 'Communication.model', // remove this pattern from entity names
proxy: { // Ext.util.ObjectTemplate
type: "ajax",
url: "/json?cmd=communication.api&entity={entityName}",
reader: {
type: "json",
rootProperty: "{entityName:lowercase}"
}
}
}
});
От нее наследую:
Ext.define("Communication.model.layout.Tabs", {
extend: "Communication.model.Base",
fields: [
"name"
]
});
EntityName получается "layout.Tabs". С сервера возвращаю json, созданный из следующей структуры:
my $data = {
"layout.tabs" => [
{name=>"Summary"},
{name=>"Access"},
{name=>"s1"},
{name=>"s2"},
]
};
Но вот когда я эту модель ("Communication.model.layout.Tabs") подключаю к стору и загружаю его, он не видит данные.
var store = new Ext.data.Store ({
model: "Communication.model.layout.Tabs"
});
store.load({
callback:function(records, operation, success){
console.log(success);
console.log(records);
}
});
В логе я вижу что success=true, но records - пустой массив. Если я формирую json как простой массив, не используя rootProperty, то данные приходят нормально. Вопрос: зачем тогда вообще этот параметр? Я чего то не понимаю... Как им пользоваться?
|
|
15.07.2014, 14:43
|
Профессор
|
|
Регистрация: 27.04.2012
Сообщений: 1,410
|
|
rootProperty: "{entityName:lowercase}"
я честно говоря с таким механизмом не работал, могу предположить, что {entityName:lowercase} заменяет на какое то значение, нет?
и что приходит с сервера?
|
|
15.07.2014, 16:24
|
|
Профессор
|
|
Регистрация: 06.06.2014
Сообщений: 292
|
|
Я же писал... если json с сервера включает в себя rootProperty и в нем уже данные то в сторе пусто. Если отправляю просто массив - в сторе то что нужно.
|
|
15.07.2014, 18:23
|
Профессор
|
|
Регистрация: 19.11.2012
Сообщений: 178
|
|
Попробовал разобраться, но не проверял...
{
rootProperty: "{entityName:lowercase}"
}
По частям:
rootProperty - имя ключа в приходящем с сервера JSONe, который содержит массив данных/записей/строк. В нашем случае - "layout.tabs".
entityName - название модели, причём урезанное. От полного имени класса модели отрезается первая часть, которая указана в нашем случае здесь:
{
schema: {
namespace: 'Communication.model'
}
}
Т.е.: "Communication.model.layout.Tabs" - 'Communication.model' = "layout.Tabs"
lowercase - имя функции для преобразования имени модели. Ожидаем, что из урезанного имени модели "layout.Tabs" в результате этого преобразования получится ключ в присылаемом с сервера JSONe "layout.tabs".
Смотрите подробнее в разделе "Relative Naming": Ext.data.schema.Schema
В нашем случае, неймер в schema не указан, используется дефолтный.
С этой точки зрения, код написан верно и должен работать.
Меня насторожили некоторые вещи. Например, в исходниках Ext.data.schema.Namer я не обнаружил lowercase. Там только присутствуют: undotted, uncapitalize, pluralize, underscore, singularize. Может в этом дело?
|
|
16.07.2014, 14:03
|
|
Профессор
|
|
Регистрация: 06.06.2014
Сообщений: 292
|
|
novikov, спасибо за наводку. Буду смотреть.
У меня вот назрел еще вопрос: а зачем вообще модель как сущность, что она дает? Я пока вижу что в ней можно определить схему, это плюс к стандартизации запросов. А еще? Я думал там есть некий механизм контроля, иными словами попытка вызвать get с неопределенным в модели полем должна привести к варнингу хотя бы... Но нет, ничего подобного. Вы не могли бы в нескольких фразах написать плюсы моделей?
|
|
16.07.2014, 18:08
|
Профессор
|
|
Регистрация: 19.11.2012
Сообщений: 178
|
|
В 5 версии стало необязательным перечисление всех полей.
It may seem contradictory in this context, but in Ext JS 5, you are no longer required to declare a Model’s fields.
Чтобы задействовать валидацию поля, нужно в его определение добавить:
{
validators: ['presence']
}
Валидатор можно написать кастомный. По ссылке выше ещё говорят о том, что упростилась работа с внешними ключами. Данные в связанные модели должны подгрузиться автоматом, если в модели определён прокси. Модели могут использоваться в формах. Модели нужны для определения сторов/хранилищ. В них они используются для хранения состояния записи - "изменена" и "удалена". Это полезно для отправки пакетных запросов на сервер, а не одиночных.
|
|
16.07.2014, 18:45
|
|
Профессор
|
|
Регистрация: 06.06.2014
Сообщений: 292
|
|
Хорошо, а вот у меня как назрел еще вопрос по моделям )
Есть например модель для авторов: айди и имя. Есть модель для книг: айди книги, айди автора, заголовок. Теперь я хочу вывести список книг. Делаю грид, в сторе указываю модель "книга". Вопрос: как отобразить имя автора вместо его айди? Переписать рендерер в гриде? Или есть более "умные" методы?
|
|
09.11.2016, 07:34
|
|
Аспирант
|
|
Регистрация: 12.05.2016
Сообщений: 95
|
|
Infarch, Вы разобрались в этом вопросе? У меня он как раз назрел сейчас
Тут вот:
http://moduscreate.com/associations-in-ext-js-5/
Пишут что все должно быть максимально просто. Указал reference в поле и в ответ уже должны идти связанные данные.
Есть базовая модель у меня:
Ext.define('MyApp.model.Base', {
extend: 'Ext.data.Model',
schema: {
namespace: 'MyApp.model'
}
});
Модель должностей:
Ext.define('MyApp.model.dictionaries.positions.Positions', {
extend: 'MyApp.model.Base',
fields: [
{
type: 'int',
name: 'id'
},
{
type: 'string',
name: 'value'
},
{
type: 'string',
name: 'valueEn'
},
],
proxy: {
type: 'api',
url: MyApp.Global.getApiUrl() + 'api/v1/positions'
}
});
Модель сотрудников:
Ext.define('MyApp.model.employees.Employees', {
extend: 'MyApp.model.Base',
fields: [
{
type: 'int',
name: 'id'
},
{
name: 'profile_pic'
},
{
type: 'string',
name: 'lastname'
},
{
type: 'string',
name: 'firstname'
},
{
type: 'string',
name: 'middlename'
},
{
type: 'int',
name: 'positionId',
reference: 'dictionaries.positions.Positions'
}
],
proxy: {
type: 'api',
url: MyApp.Global.getApiUrl() + 'api/v1/employees'
}
});
Указал я reference, но связанных данных не вижу.
|
|
09.11.2016, 11:17
|
|
Профессор
|
|
Регистрация: 06.06.2014
Сообщений: 292
|
|
Я не разобрался в свое время и отказался от такой идеи. Ибо по всему выходило что надо писать рендерер для такой колонки и в нем уже извлекать данные. Вместо этого я просто стал читать с сервера комбинированные списки.
А по той ссылке что вы дали я вижу ту самую идею. Они так и пишут: If you inspect the Customers store, you’ll see that each record now has an addresses() getter that will return a store of this customer’s addresses.. Мы получаем геттер, но чтоб вывести его результат в списке нам таки нужен рендерер.
|
|
17.11.2016, 04:17
|
|
Аспирант
|
|
Регистрация: 12.05.2016
Сообщений: 95
|
|
Сообщение от Infarch
|
Вместо этого я просто стал читать с сервера комбинированные списки.
|
Через JOIN забираете данные? Какой JSON должен быть примерно понятно, только как его сформировать пока не ясно.
Разобрался со связями, но для меня оказалось проще использовать денормализацию (+1 поле в БД) вместо манипуляций с рендерером.
Вот хороший Фидл по теме:
https://fiddle.sencha.com/#fiddle/1h22
Несколько моментов:
1. Нормально это все работает только если использовать механизм сессий. Если даже в фиддле этом закомментировать session: true в 3х местах, то все нахрен отвалится.
2. Обязательно все store прописывать через ViewModel, у которых также включать сессию. Без сессии и ViewModel на каждую связанную запись будет идти запрос в БД!
3. В рендерере надо также отлавливать NULL, если он есть и выдавать вместо него пустую строку (может есть какая опция на эту тему, но пока не нашел).
3. Группировка по связанному полю в Grid'е работает, но фильтрация уже, увы, недоступна.
|
|
|
|