Для моделей, как и для любых других объектов в Ember-приложении, мы можем создавать так называемые вычислимые свойства. К примеру, мы хотим, чтобы вместо фамилии менеджера на форме редактирования заказа отображались фамилия и инициалы: для этого нам понадобится создать новое свойство на основе фамилии, имени и отчества у сотрудника. Так как подобные данные могут понадобиться и на других формах, вынесем эти изменения непосредственно в модель сотрудника, так как эта модель вычитывается каждый раз, когда на какой-либо форме требуется информация о сотруднике.

Добавим новое вычислимое свойство nameWInitials в модель сотрудника:

app → models → i-i-s-shop-employee.js

import { computed } from '@ember/object';
let Model = EmberFlexberryDataModel.extend(OfflineModelMixin, EmployeeMixin, Validations, {
  nameWInitials: computed('lastName', 'firstName', 'middleName', function() {
    let lastName = this.get('lastName');

    let firstName = this.get('firstName');
    let firastNameInitial = firstName.substr(0, 1).toUpperCase();

    let middleName = this.get('middleName');
    let middleNameInitial = middleName.substr(0, 1).toUpperCase();

    return `${lastName} ${firastNameInitial}.${middleNameInitial}.`;
  }),

  fullName: computed(function() {
    let lastName = this.get('lastName');
    let firstName = this.get('firstName');
    let middleName = this.get('middleName');

    return `${lastName} ${firstName} ${middleName}`;
  }),
});

Будем использовать это свойство на форме редактирования Заказа для отображения выбранного значения лукапа (свойство displayAttributeName), соответствующего полю Менеджер:

app → templates → i-i-s-shop-order-e.js

<div class="field">
    <label>{{t "forms.i-i-s-shop-order-e.manager-caption"}}</label>
    {{flexberry-lookup
      choose="showLookupDialog"
      remove="removeLookupValue"
      value=model.manager
      displayAttributeName="nameWInitials"
      autocomplete=true
      relationName="manager"
      projection="EmployeeL"
      title=(t "forms.i-i-s-shop-order-e.manager-caption")
      readonly=readonly
      componentName="managerLookup"
    }}
    {{flexberry-validationmessage error=(v-get validationObject "manager" "messages")}}
</div>

Проверим внесенные изменения, создав новый заказ со следующими данными:

Заказ 1:

Менеджер: Евгеньева (Евгения Евгеньевна, таб. номер 4)

Фамилия И.О. связанного с заказаом сотрудника-менеджера

Как мы видим, имя отобразилось так, как мы и задумывали.

Далее сохраним заказ и перезагрузим страницу. После перезагрузки страницы мы можем увидеть, что выбранное ранее значение поля “Менеджер” у заказа не отображается!

Отсутствующее значение лукапа для Менеджера

Логи ошибки

Если мы откроем консоль, то в консоли мы увидим ошибку в виде попытки получения подстроки у несуществующего объекта. Перейдем по соответствующей ссылке - мы увидим, что имя менеджера (в модели сотрудника) не существует. Почему так происходит?

Дело в том, что свойство firstName (как и свойство middleName) не было указано в проекции OrderE для свойства Manager класса Order во Flexberry Designer (именно эта модель в Ember-приложении загружается, когда открывается форма редактирования, при этом используется E-проекция модели):

app → mixins \ regenerated → models → i-i-s-shop-order.js

Проекция OrderE

Так как свойство firstName не указано в проекции, то при загрузке модели для формы редактирования оно не подгружается из базы данных. Поэтому, при обращении к модели employee, инстанцией которой является менеджер, оно имеет значение undefined. Чтобы это исправить, нужно дополнить проекцию модели заказа. Для этого откроем Flexberry Designer, найдем там диаграмму классов “Сущности” и откроем на редактирование свойства класса Order:

Order → [ПКМ] → ORM: Редактировать свойства → Представления → OrderE

Добавление невидимых полей в OrderE

Добавим два свойства для менеджера, firstName и middleName, зададим им пустые (~) заголовки и скроем их для отображения. Теперь остается перегенерировать модель и, соответственно, исправленное представление, соответствующее классу Order:

Перегенерация модели для класса Order

Перегенерируем также и бэкенд: в настоящее время не существует способа перегенерации отдельных классов на бэкенде, поэтому она запускается целиком для всех классов. Однако можно запустить перегенерацию не всего бэкенда, а исключительно объектов данных (Shop.Objects):

Перегенерация проеекта Objects бэкенда

После перегенерации приложений, перезапустим как фронтенд, так и бэкенд, и проверим, получилось ли нам исправить ошибку:

Фамилия И.О. менеджера показывается при загрузке

Теперь все работает корректно. При этом в проекции заказа появились соответствующие невидимые свойства:

Добавленные свойства в проекцию модели заказа

Почему же при создании нового заказа инициалы имени и отчества прогрузились, а после перезагрузки страницы - нет? На самом деле, даже при перезагрузке мы могли бы получить валидное значение, если бы после перезагрузки открыли лукап, а потом закрыли его. Дело в том, что при выборе менеджера на форме редактирования подгружается списковая форма в соответствии с указанной проекцией (так же, как и для обычной списковой формы сотрудников), что приводит к загрузке необходимых данных в локальное хранилище (store) Ember-приложения. Иными словами, ошибка, которую мы наблюдали при перезагрузке формы связана с тем, что в store отсутствовали необходимые данные для заполнения модели сотрудника и вычисления его инициалов. Расширив проекцию заказа, мы добавили обязательную загрузку нужных нам свойств сразу при открытии формы редактирования.


Самостоятельно измените отображаемые свойства для следующих лукапов:

Накладная

Товар выдал → Фамилия И.О. (nameWInitials)
Список товаров к выдаче:
Товар → <код товара>. Наименование товара (nameWCode)

Заказ

Содержимое заказа:
Товар → <код товара>. Наименование товара (nameWCode)

Склад

Кладовщик → Фамилия Имя Отчество (fullName) Список товаров: Товар → <код товара>. Наименование товара (nameWCode)

Подсказка: настройку свойства для отображения выбранного значения лукапа (displayAttributeName) внутри детейлового компонента можно произвести в методе getCellComponent контроллера соответствующего агрегатора (там уже сгенерированы соответствующие конструкции для лукапов).


Итог

Следить за настройкой проекций необходимо постоянно, так как иногда в проекции модели могут быть не указаны все необходимые свойства для корректного отображения данных на какой-либо форме. Всегда проверяйте, как ведет себя форма при перезагрузке страницы.

Перейти