flexberry-groupedit
предназначен для работы с детейлами на форме редактирования.
Чтобы добавить groupedit на страницу, в шаблоне нужно указать:
{{flexberry-groupedit
componentName="ordersGroupEdit"
defaultSortingButton=true
class="attached"
modelProjection=modelProjection.attributes.orders
content=model.orders
readonly=readonly
orderable=false
}}
Свойства Flexberry Groupedit
Свойство | Краткое описание |
---|---|
Свойства componentName и readonly |
Свойства из базового контрола. |
modelProjection |
Определяет представление, которое будет отображаться. |
content |
Определяет записи, редактируемые в контроле. |
cellComponent |
Метод, определяющий, каким контролом редактируется компонент. |
defaultSortingButton |
Флаг, определяющий, отображать ли кнопку установки сортировки по умолчанию. Значение по умолчанию: true. |
orderable |
Флаг, определяющий, возможно ли производить сортировку по столбцам в компоненте (если значение флага будет изменено на true , потребуются дополнительные настройки, о чём ниже). |
showDeleteMenuItemInRow |
Флаг, определяющий, отображать ли пункт контекстного, меню мобильного шаблона FGE, Удалить запись . Значение по умолчанию: false. |
showEditMenuItemInRow |
Флаг, определяющий, отображать ли пункт контекстного, меню мобильного шаблона FGE, Редактировать запись . Значение по умолчанию: false. |
showDeleteButtonInRow |
Флаг, определяющий, отображать кнопку - для удаления записи в браузерном и мобильном шаблоне. Значение по умолчанию: false. |
singleColumnHeaderTitle |
Заголовок для мобильного представления FGE, вместо названий колонок. |
Свойства, используемые для настройки редактирования в отдельном роуте:
rowClickable
rowClick
editOnSeparateRoute
Особенности реализации
- Flexberry Groupedit состоит из двух компонент:
GroupeditToolbar
иObjectListView
. - Свойство
class
применяется кObjectListView
.
Сортировка элементов
Если для флага orderable
выставить значение true
, то требуется дополнительно задать настройки:
{{flexberry-groupedit
...
orderable=true
sortByColumn=(action "sortByColumn")
addColumnToSorting=(action "addColumnToSorting")
}}
sortByColumn
- действие (action) контроллера, которое должно быть выполнено для сортировки по столбцу.addColumnToSorting
- действие (action) контроллера, которое должно быть выполнено для добавления сортировки по столбцу.
Использовать сортировку в шаблоне можно, если в контроллере шаблона были определены действия (action) с именами sortByColumn
и addColumnToSorting
. Синтаксис addColumnToSorting=(action \"addColumnToSorting\")
определяет, что используется ember closure action.
Встраивание компонентов в groupedit
Компонент flexberry-groupedit
- это таблица, в ячейки которой можно встраивать любые компоненты, наследуемые от flexberry-base-component.
Для встраивания компонентов flexberry-groupedit находит метод getCellComponent
в текущем контроллере, и вызывает его при формировании каждой ячейки таблицы.
Метод getCellComponent
уже определен в базовом контроллере формы редактирования (ember-flexberry/controllers/edit-form.js
), его логика направлена на встраивание компонентов в зависимости от типа данных в ячейке, и выглядит следующим образом:
// ...
getCellComponent: function(attr, bindingPath, modelClass) {
var cellComponent = {
componentName: 'flexberry-textbox',
componentProperties: null
};
if (attr.kind === 'belongsTo') {
cellComponent.componentName = 'flexberry-lookup';
return cellComponent;
}
var modelAttr = !Ember.isNone(modelClass) ? Ember.get(modelClass, 'attributes').get(bindingPath) : null;
if (attr.kind === 'attr' && modelAttr && modelAttr.type) {
switch (modelAttr.type) {
case 'boolean':
cellComponent.componentName = 'flexberry-checkbox';
break;
case 'date':
cellComponent.componentName = 'flexberry-datepicker';
break;
case 'file':
cellComponent.componentName = 'flexberry-file';
break;
default:
// Current cell type is possibly custom transform.
var modelAttrType = getOwner(this)._lookupFactory('transform:' + modelAttr.type);
// Handle enums (extended from transforms/enum-base.js).
if (modelAttrType && modelAttrType.isEnum) {
cellComponent.componentName = 'flexberry-dropdown';
cellComponent.componentProperties = {
items: modelAttrType.create().getAvailableValuesArray()
};
}
break;
}
}
return cellComponent;
}
Если на прикладной форме редактирования требуется встраивать прикладной компонент в ячейки groupedit, то необходимо будет переопределить метод getCellComponent
в прикладном контроллере, унаследованном от базового контроллера формы редактирования (ember-flexberry/controllers/edit-form.js
).
import EditFormController from 'ember-flexberry/controllers/edit-form';
export default EditFormController.extend({
title: 'My edit form',
//...
getCellComponent: function(attr, bindingPath, model) {
if (...) {
return {
componentName: 'my-component',
componentProperties: null
};
}
if (...) {
return {
componentName: 'my-another-component',
componentProperties: {
myAnotherComponentProperty1: 'someValue',
myAnotherComponentProperty2: 4815162342
}
};
}
return this._super(...arguments);
}
//...
});
При этом важно, чтобы встраиваемый компонент наследовался от базового компонента (ember-flexberry/components/flexberry-base-component.js
), и если в компоненте переопределен метод init
, то в конце прикладной инициализации обязательно должен вызываться метод инициализации из базового класса, так как там определена логика, инициализирующая свойства компонента из объекта переданного в возвращаемом значении метода getCellComponent
по ключу componentProperties
.
Редактирование детейлов в отдельном роуте
Настройка шаблонов и моделей агрегатора и детейла, сериализатора агрегатора и контроллера детейла для реализации возможности редактирования в отдельном роуте является частным случаем использования компонента (например, при работе на мобильных устройствах).
При этом следует учитывать некоторые особенности приминения:
- Изменения в агрегаторе и детейлах сохраняются в БД только при нажатии кнопки
Сохранить
на форме агрегатора. - На странице детейла есть только две кнопки:
Сохранить
иЗакрыть
(на форме нет кнопки, чтобы откатить состояние детейла на момент захода на форму). - При нажатии на кнопку
Сохранить
на странице детейла происходит возврат на страницу агрегатора без сохранения изменений в БД.
Настройка шаблона агрегатора и роутера
В шаблоне формы редактирования агрегатора у контрола flexberry-groupedit
определить следующие свойства:
{{flexberry-groupedit
...
rowClickable=true
rowClick='rowClick'
editOnSeparateRoute=true
}}
rowClickable
- флаг, определяющий, следует ли обрабатывать нажатие на строчку. По умолчанию имеет значениеfalse
, для редактирования детейла в отдельном роуте нужно задатьtrue
.rowClick
- действие, выполняемое при нажатии на строчку. По умолчанию имеет значение “rowClick”, для редактирования детейла в отдельном роуте нужно, чтобы действие (action) с заданным в свойстве именем было определено в контроллере или роуте (rowClick
определено в базовом роуте формы редактирования).
rowClick
реализован таким образом, что в случае, если детейл сохранён, то будет произведена переадресация на роут как modelName/:id
, а если не сохранён, то modelName.new
(соответственно, роутер должен быть настроен, чтобы переадресация могла пройти корректно).editOnSeparateRoute
- флаг, определяющий, следует ли редактировать детейл в отдельном роуте. По умолчанию имеет значениеfalse
. При задании значения “true” изменяется внешний видflexberry-groupedit
: отключается возможность редактирования непосредственно в контроле, при нажатии на кнопкуДобавить
теперь создаётся новая запись и сразу происходит переадресация на роут редактирования.
Настройка шаблона детейла
Чтобы была возможность редактировать детейл в отдельном роуте, соответствующая форма должна быть создана.
Если предполагается, что форма редактирования детейла может быть использована не только с формы агрегатора, но и со списковой формы детейлов, то для настройки отображения кнопок Сохранить
, Удалить
, Закрыть
можно использовать условия, представленные в статье Формы редактирования и создания.
Настройка контроллера детейла
Контроллер формы редактирования детейла должен наследоваться от detail-edit-form
вместо edit-form
. В detail-edit-form
присутствует дополнительная логика, организующая корректное взаимодействие между формами агрегатора и детейла. В случае, если определено, что пользователь попал на форму детейла не с формы агрегатора, то будет выполняться логика базового контроллера edit-form
.
import DetailEditFormController from 'ember-flexberry/controllers/detail-edit-form';
export default DetailEditFormController;
Настройка моделей агрегатора и детейла
При описании модели агрегатора важно проверить, что проставлена детейловая inverse-связь.
var Model = BaseModel.extend({
...
orders: DS.hasMany('order', { inverse: 'employee', async: false }),
});
При описании модели детейла важно проверить, что проставлена inverse-связь на агрегатора.
var Model = BaseModel.extend({
...
employee: DS.belongsTo('employee', { inverse: 'orders', async: false })
});
Настройка сериализатора агрегатора
Важно, чтобы сериализаторы для агрегатора и детейла были настроены корректно.
Дополнительные особенности реализации
- У базового контроллера формы редактирования есть свойство
returnToAgregatorRoute
, которое определяет, следует ли производить настройки для потенциального возвращения на предыдущий роут агрегатора. По умолчанию в базовом контроллере значениеfalse
. В базовом контроллере детейла данное значение переопределено наtrue
(при необходимости можно в прикладном контроллере детейла поменять его обратно наfalse
, чтобы не происходило возвращение). Вычитка данного флага происходит в методе роута setupController. - Для организации сохранения информации между роутами агрегатора и детейла используется специальный сервис
detail-interaction
. Данный сервис не предназначен для использования на прикладных проектах. - В базовый роут формы редактирования миксинится свойство
newRoutePath
, где определяется, каким образом по роуту модели определяется роут для новой записи. Сейчас метод реализован какcurrentPath + '.new'
. Потенциально этот метод можно переопределить на прикладном роуте.
Редактирование детейлов в отдельном роуте во Flexberry Groupedit с сохранением
Существует режим работы flexberry-groupedit
, при котором редактирование детейла происходит на отдельном роуте, при этом, при переходе с роута агрегатора на роут детейла, происходит сохранение агрегатора, а при переходе обратно - сохранение детейла.
Настройка данного варианта аналогичная описываемому выше способу. В шаблоне контрола при этом нужно выставить один дополнительный флаг saveBeforeRouteLeave
.
{{flexberry-groupedit
...
rowClickable=true
rowClick='rowClick'
editOnSeparateRoute=true
saveBeforeRouteLeave=true
}}
saveBeforeRouteLeave
- флаг, определяющий, следует ли сохранять текущую модель при переходах между агрегатором и детейлом. По умолчанию имеет значение false
.
О том, как функционируют кнопки на такой детейловой форме, описано в статье Формы редактирования и создания.
Вычислимые свойства в getCellComponent
Что бы иметь возможность, изменять свойства, встроенного в ячейку компонента, этот компонент должен использовать миксин DynamicPropertiesMixin.
Свойства компонента, описанные объектом componentProperties
, в хуке контроллера getCellComponent
, будут переданны с использованием свойства dynamicProperties
из миксина.
Поэтому, при изменении свойств объекта componentProperties
, эти изменения будут выполнены для компонента.
Пример с реализацией:
// app/controllers/my-controller.js
import Controller from '@ember/controller';
import { observer } from '@ember/object';
export default Controller.extend({
checkboxValue: false,
lookupReadonly: observer('checkboxValue', function() {
this.set('componentDynamicProperties.readonly', this.get('checkboxValue'));
}),
getCellComponent(attr, bindingPath, model) {
let cellComponent = this._super(...arguments);
if (attr.kind === 'belongsTo') {
this.set('componentDynamicProperties', {
choose: 'showLookupDialog',
remove: 'removeLookupValue',
displayAttributeName: 'name',
required: true,
relationName: 'author',
projection: 'ApplicationUserL',
autocomplete: true,
readonly: false,
});
cellComponent.componentProperties = this.get('componentDynamicProperties');
}
return cellComponent;
},
});
Вы можете посмотреть пример с реализацией на тестовом стенде.
Ordered свойства в groupedit
При добавлении в представление, groupedit-а ordered-свойства в нем появятся некоторые особенности, которые следует учитывать:
- Сортировка в groupedit-е будет по ordered свойству. При этом обычная сортировка в ГЕ будет отключена и ее нельзя включить.
- При вставке/удалении строк в groupedit осуществляется автоматический пересчет ordered-атрибута по всем строкам.
- В groupedit, когда в модели есть ordered-атрибут, появляется возможность перемещать строки вверх-вниз через стрелочки. При этом производиться автоматический пересчет значения ordered-атрибута тех строк, у которых изменилась позиция.
- Если ordered-атрибут отображается в ГЕ для пользователя, то соответствующие значения данного атрибута будет readonly.