Иногда возникают задачи, связанные с реализацией презентационной логики. В качестве примера рассмотрим реализацию логики формы Заказа при изменении статуса заказа на “Оплаченный”:

  1. сделать поле “Дата оплаты” обязательным при переводе Заказа в статус “Оплаченный” (до сохранения);
  2. нужно исключить возможность изменять любые поля, кроме поля “Дата отгрузки” после перевода в статус “Оплаченный” - следовательно, их нужно заблокировать;
  3. после списания товара нужно убрать валидацию с Содержимого заказа, т.к. необходимого объема товара на складах может уже не быть;
  4. необходимо отписаться от обзервера на товар (Цена с налогом), чтобы цена товаров уже не менялась (цену товаров в конкретном заказе стоит фиксировать как минимум в момент подтверждения оплаты заказа, оптимально - когда выписывается накладная по заказу).

С учетом данных изменений, форма приобретет законченный в отношении события оплаты заказа вид.

Условные валидаторы

Для того, чтобы валидатор на обязательность поля “Дата оплаты” срабатывал не всегда, мы должны отслеживать Статус заказа. Для таких ситуаций аддон ember-cp-validations позволяет настраивать условия работы валидатора. Реализуем этот механизм на примере валидации поля order.paymentDate:

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

Валидатор для поля paymentDate заказа

Нам нужно добавить сюда один из встроенных валидаторов - валидатор на обязательность значения - presence (полный список доступных валидаторов аддона можно посмотреть тут - панель Classes):

paymentDate: {
  descriptionKey: 'models.i-i-s-shop-order.validations.paymentDate.__caption__',
  validators: [
    validator('ds-error'),
    validator('date'),
    validator('presence', true)
  ],
},

Если мы оставим его в таком виде, то валидация срабатывать будет всегда. Поэтому добавим условие валидации:

import OrderStatusEnum from '../enums/i-i-s-shop-order-status';
import { computed } from '@ember/object';
paymentDate: {
  descriptionKey: 'models.i-i-s-shop-order.validations.paymentDate.__caption__',
  validators: [
    validator('ds-error'),
    validator('date'),
    validator('presence', 
      presence: true,
      disabled: computed('model.status', function() {
        return this.get('model.status') !== OrderStatusEnum.Paid;
      })
    }),
  ],
},

Проверим, как работает валидатор на примере Заказа 1:

Условный валидатор не работает в форме редактирования заказ

Если статус заказа перевести в “Оплаченный”, то валидатор будет срабатывать:

Условный валидатор работает в форме редактирования заказ

Все работает корректно.


Самостоятельно настройте валидацию поля “Дата и время отгрузки” формы редактирования Накладной: поле обязательно для заполнения, если накладная имеет статус “Отгруженная”


Блокировка полей формы

Наиболее простой и эффективный способ изменения внешнего вида форм - это настройка шаблона. Ранее мы уже меняли элементы шаблона, настраивая режим полей “только для чтения” в статичном (постоянном) режиме. Теперь для части полей нам необходимо настроить динамическую блокировку: поля должны блокироваться только в том случае, когда заказа имеет статус “Оплаченный” и не осталось никаких несохраненных изменений. Блокировать будем всю форму целиком, так как Оплаченный заказ нельзя отменить или вновь сделать новым.

Добавим в модель Заказа новое вычислимое свойство isPaid:

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

import OrderStatusEnum from '../enums/i-i-s-shop-order-status';
import { computed } from '@ember/object';
let Model = DocumentModel.extend(OrderMixin, Validations, {
  isPaid: computed('status', function() {
    const status = this.get('status');
    const dirtyAttributes = this.get('hasDirtyAttributes');

    return status === OrderStatusEnum.Paid && !dirtyAttributes;
  })
});

Далее нам нужно присвоить значение свойства модели isPaid свойству readonly для всех полей формы - по умолчанию оно имеет значение false (разрешено для редактирования). В качестве примера рассмотрим изменения для поля status:

app → templates → i-i-s-shop-order.hbs

Проверим, как работает блокировка полей на примере Заказа 1:

Поля заказа не заблокированы

Переведем в статус “Оплаченный” и сохраним:

Поля заказа заблокированы

Все работает корректно.


Самостоятельно настройте:

  1. отключение валидации на форме Заказа с использованием нового свойства модели isPaid. При возникновении трудностей обратитесь к пункту “Условные валидаторы” и документации по аддону;
  2. скройте кнопки “Сохранить” и “Удалить” для формы редактирования заказа в состоянии “Оплачено”.

Условное поведение обзервера

До сих пор обзервер на обновление срабатывал каждый раз при загрузке формы, на которой он работает. В частности, если мы меняли цену товара и обновляли страницу заказа, то обзервер “подхватывал” новую цену и изменял все поля, связанные с ценой товара. Проверим данное поведение на примере Заказа 2:

  1. Изменим цену товара "Монитор Samsung C24F390FHI" Изменение цены
  2. Проверим состояние Заказа 2 (корректное поведение - форма заблокирована, цена с налогом у данного товара - 9900 руб.) В заказе также изменилась цена

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

Ограничим срабатывание обзервера на пересчет Цены с налогом в детейле на форме редактирования Заказа:

app → models → i-i-s-shop-order-item.js

let Model = EmberFlexberryDataModel.extend(OfflineModelMixin, OrderItemMixin, Validations, {
  taxes: 10,

  // Цена с налогом
  _priceWTaxesChanged: on('init', observer('product', function() {
    if (!this.get('order.isPaid')) {
      once(this, '_priceWTaxesCompute');
    }
  })),

  ...

}

Так как все остальные обзерверы на форме связаны со значением поля “Цена с налогом”, то, остановив срабатывание этого обзервера, мы “отключим” и все остальные.

Проверим внесенные изменения на примере Заказа 2:

Поля заказа заблокированы

Все работает корректно.


Самостоятельно настройте блокировку формы заказа для статуса “Отмененный”.

Подсказка: можно расширить функционал существующей блокировки для статуса “Оплаченный” (isPaid) до общего врианта isBlocked.


Итог

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

Итоговое приложение размещено в репозитории: стадии до и после работы, скрипт на создание структуры базы данных, приложение со всеми доработками (кроме самостоятельных заданий).

Самостоятельная работа

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

  1. запретить создание Накладной пользователем (убрать кнопку “Добавить” в списковой форме Накладные);

Перейти