Валидация на формах редактирования в базовом варианте автоматически реализуется при генерации приложения на основании данных диаграммы классов. Так, например, выглядит валидация поля “Цена за ед.” на форме редактирования “Товара”:
Настройка валидации в аддоне ember-flexberry
версий 3.x.x осуществляется при помощи аддона ember-cp-validations (для версий 2.x.x используется аддон ember-validations). Он не только предоставляет определенный набор готовых валидаторов, но и также позволяет писать кастомные.
В одном их предыдущих разделов, “Добавление тестовых данных”, мы говорили о том, что на форме “Заказ” существует поле, которое при заполнении должно валидироваться особым образом:
Так, при выборе товара и указании количества этого товара, необходимо проверять, есть ли в наличии на всех складах, вместе взятых, необходимое количество указанного товара.
Для решения это задачи напишем свой собственный валидатор.
Прежде всего, откроем новый терминал (Терминал
→ Новый терминал
) и выполним команду
ember generate validator check-product-amount
Далее, откроем сгенерированный валидатор:
app → validators → check-product-amount.js
Мы видим сгенерированную “заготовку” для кастомного валидатора. Код для валидации мы будем размещать в методе validate (выделенная зеленым строка №5). По умолчанию данный метод возвращает значение true
: если мы прямо сейчас подключим этот валидатор, то он будет для любого проверяемого значения сообщать, что валидация прошла успешно (не будет “выкидывать” ошибок).
Для того, чтобы реализовать требуемый вариант валидации, нам, прежде всего, необходимо вычитать все склады. Для этого в функции validate
для начала получим сервис store (специальный сервис библиотки Ember Data):
Подробнее о функции inject
можно почитать тут.
Далее нам требуется вычитать актуальные сведения о складах и хранящихся на них товарах из БД. Для этого воспользуемся клиентским языком запросов, который предоставляется аддоном ember-flexberry-data (устанавливается автоматически вместе с аддоном ember-flexberry):
1. добавить оператор return перед вызовом асинхронного запроса;
2. возвращать значение
true
или false
в колбэке, который вызывается в результате выполнения асинхронного запроса (после того, как соответствующий промис "разрезолвится").В параметре storehouses
колбэка, который срабатывает в результате успешного выполнения запроса store.query, у нас теперь доступны данные обо всех вычитанных складах. Нам нужно просмотреть товары у каждого склада и сохранить данные о наличии товаров и их общем количестве. Для этого создадим объект products и переберем все склады и все товары на каждом складе, сохраняя суммарное количество товаров в созданном объекте:
Теперь в объекте products
находятся данные о количестве товаров в формате
“<id товара>: <количество>”.
Далее нам нужно получить само значение валидируемого поля (валидатор срабатывает при каждом изменении значения поля), то есть id товара
из строки заказа и сравнить его с данными, хранящимися в объекте products
. Значение валидируемого поля передается в параметре value
метода validate
, но id товара
нужно будет получить из связанной с валидируемым полем модели. Для этого раскомментируем часть параметров у функции validate
и получим id товара у модели:
Если товар в строке заказа не выбран,то валидацию мы выполнять не будем. По умолчанию тогда валидатор будет сообщать, что все в порядке (ошибка не будет выводиться).
Если же товар в строке заказа выбран, то необходимо получить соответствующее суммарное количество из объекта products
и сравнить его с валидируемым значением:
Остается сформировать сообщение, которое валидатор вернет в случае, если на складах нет требуемого количества товара для формирования заказа:
Поскольку данный валидатор выполняет сетевой запрос к серверу, нам также необходимо обработать ситуацию, в которой сетевой запрос выполняется неуспешно, и вернуть в этом случае соответствующее сообщение:
Теперь мы можем подключить созданный валидатор к нужной модели и проверить его работоспособность:
app → mixins/regenerated → models → i-i-s-shop-order-item.js
Ранее в разделе “Добавление тестовых данных” мы добавили на склады следующие товары:
- Монитор Samsung C24F390FHI - 4 + 1 = 5 (шт.)
- Системный блок Acer Aspire XC-330 DT.BD2ER.001 - 2 + 0 = 2 (шт.)
- Монитор игровой MSI Optix MAG241CP - 1 + 2 = 3 (шт.)
Так как нам необходимо проверить в том числе ситуацию, когда товара на складах нет совсем, уберем позицию “Системный блок игровой Lenovo Legion T530-28ICB MT (90JL00M4RS)” со 2 склада. После этого перейдем к списку “Заказов” и создадим новый заказ. Сохранять мы его не будем, но протестируем при этом валидацию:
- Системный блок игровой Lenovo Legion T530-28ICB MT (90JL00M4RS) - 1 (шт.)
- Монитор Samsung C24F390FHI - 5 (шт.)
- Монитор Samsung C24F390FHI - 6 (шт.)
Как мы видим, валидация работает корректно.
Для отладки работоспособности валидатора можно использовать функцию console.log()
. Однако по умолчанию настройки линтинга кода запрещают использование конструкции console.log()
. Для того, чтобы эта ошибка не выводилась при сборке приложения, нужно добавить в файле .eslintrc.js
правило:
Для применения этого правила следует перезапустить приложение (нажать Ctrl+C, и затем выполнить команду ember s в терминале). Чтобы можно было отлаживать валидатор через вывод логов в консоль, его также следует подключить к нужной модели.
Итог
Кастомные валидаторы используются в тех случаях, когда требуется реализовать специфические правила валидации данных на форме. В остальных случаях рекомендуется использовать стандартные валидаторы аддона ember-cp-validations.
В следующих разделах мы будем выполнять настройку не только кастомных, но и и стандартных валидаторов.
Самостоятельная работа
Вы можете выполнить следующие доработки в приложении самостоятельно для более детальной проработки требований к функционалу приложения:
- доработать валидацию числовых полей: проверять, что для некоторых полей значения могут быть положительные (строго больше 0) или неотрицательные (больше или равно 0).