Skip to main content

Действия

Действия N2o выполняются с помощью библиотеки Redux. Действия Redux меняют состояние React компонентов и отправляют запросы на сервер.

Местоположение действий

Действия задаются на странице <page>, в компонентах страницы, а также в меню структуры приложения <application>. Подробнее о каждом из этих случаев будет рассказано далее.

Действия в меню

Одним из вариантов использования действия является задание его в меню <menu-item> структуры приложения.

Действие в меню приложения
<application xmlns="http://n2oapp.net/framework/config/schema/application-3.0">
<header title="Хедер">
<nav>
<menu-item name="Открыть страницу">
<open-page page-id="page" route="/login"/>
</menu-item>
</nav>
</header>
</application>

Действия в кнопках страницы

Пожалуй, самым частым вариантом является использование действий в кнопках страницы.
В данном случае неважно, чем является кнопка: стандартной кнопкой, полем-кнопкой, кнопкой в ячейке или в выпадающем меню. При клике по ней будет выполняться указанное действие.

Действие в кнопке
<page xmlns="http://n2oapp.net/framework/config/schema/page-4.0">
...
<toolbar>
<button label="Сохранить документ">
<invoke operation-id="saveDocument"/>
</button>
</toolbar>
</page>

Действия на странице

При многократном использовании одного действия существует возможность вынести его в отдельный элемент <actions> при этом указав id. Для обращения к этому действию достаточно указать его идентификатор в атрибуте action-id.

Действие на странице
<page xmlns="http://n2oapp.net/framework/config/schema/page-4.0">
...
<actions>
<!-- Указываем id действия -->
<action id="save">
<invoke operation-id="saveDocument"/>
</action>
</actions>

<toolbar>
<!-- Обращаемся к действию по его id -->
<button label="Сохранить документ" action-id="save"/>
</toolbar>
</page>

Действия в виджетах

Аналогично страницам действия можно определить и внутри виджетов.

Действие в виджете
<form>
...
<actions>
<!-- Указываем id действия -->
<action id="save">
<invoke operation-id="saveDocument"/>
</action>
</actions>

<toolbar>
<!-- Обращаемся к действию по его id -->
<button label="Сохранить документ" action-id="save"/>
</toolbar>
</form>
note

Задание действия на странице или в виджете определяет область видимости. Кнопки виджета могут ссылаться на действия страницы, а вот кнопки страницы на действия виджета не могут.

Внутренние действия компонентов

Не только кнопки способны выполнять действие по клику. Это может быть клик по строке таблицы, клик по определенному полю или ячейке.
Во всех этих компонентах также есть возможность либо описать действие внутри элемента, либо обратиться по его id.

Действия в компонентах таблицы
<table>
<columns>
<column text-field-id="status">
<!-- Отправка статуса при клике по чекбокс-ячейке таблицы -->
<checkbox enabled="true">
<invoke operation-id="checkStatus"/>
</checkbox>
</column>
</columns>

<rows>
<!-- Открытие страницы при клике по строке таблицы -->
<click>
<show-modal page-id="modal"/>
</click>
</rows>
</table>

Действия открытия окон и страниц

Отрытие окон

Открытие страниц

Проброс кнопок и действий в открываемые страницы

Кнопки и действия на странице можно переопределять в открывающих страницах. Это удобно когда необходимо использовать одну и ту же страницу, отличающуюся только кнопками и действиями.

Проброс кнопок и действий в открываемые страницы
<show-modal page-id="personCard">
<actions>
<action id="saveAction">
<invoke operation-id="save"/>
</action>
</actions>
<toolbars>
<toolbar>
<!-- кнопка ссылается на прокидываемое действие saveAction -->
<button label="Сохранить" action-id="saveAction"/>
</toolbar>
</toolbars>
</show-modal>

<show-modal page-id="personCard">
<toolbars>
<toolbar>
<button label="Копировать">
<!-- действие использует прокидываемый источник ds1 -->
<copy copy-datasource="modal_ds" target-datasource="ds1"/>
</button>
</toolbar>
</toolbars>
<datasources>
<parent-datasource id="ds1"/>
</datasources>
</show-modal>

Действие редактирования списка данных без обращения к серверу

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

С помощью действия <edit-list> список может быть модифицирован одним из привычных способов. Для модификации доступны 5 возможных операций: create, createMany, update, delete, deleteMany.

Удаление нескольких строк таблицы
<table datasource="ds" selection="checkbox">
<columns>
...
</columns>

<toolbar>
<button label="Удалить выбранные строки">
<edit-list
operation="deleteMany"
datasource="ds"
model="datasource"
item-datasource="ds"
item-model="multi"/>
</button>
</toolbar>
</table>

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

Изменение выбранной строки таблицы
<form datasource="formDs">
<fields>
...
</fields>

<toolbar>
<button label="Сохранить">
<edit-list
operation="update"
primary-key="id"
datasource="tableDs"
model="datasource"
item-datasource="formDs"
item-model="resolve"/>
<close/>
</button>
</toolbar>
</form>
note

Обратите внимание на атрибут primary-key в последнем примере. В нем указывается поле, по которому среди списка записей будет искаться нужная, для операций изменения или удаления. Учтите, что указанное поле должно иметь уникальные значения.

В конце важно упомянуть о такой важной особенности действия <edit-list>, как отсутствие запроса на сервер. Можно заметить, что, если после модификации списка обновить страницу, то все данные потеряются. Однако отсутствие запроса на сохранение ни в коем случае не является недостатком действия, а скорее возможностью более гибко настроить момент, в который это сохранение произойдет.

Но как же тогда сохранить на сервер только что внесенные изменения? Для этого достаточно использовать действия <submit> или <invoke> сразу после <edit-list>. Вызов нескольких действий подряд создаст так называемую последовательность действий или мульти действие, которому и будет посвящен следующий раздел.

Подробнее о действии edit-list

Последовательность действий и ветвления

До этого момента в примерах использовались только простые одиночные действия. Они покрывают большую часть возможных случаев. Но как поступить, если необходимо выполнить несколько действий или выполнить действие при определенном условии? Об этом и пойдет речь ниже.

Мульти действия

Иногда возникает необходимость вызывать целую цепочку последовательных действий. N2o позволяет сделать это. И во всех местах, где до этого вызывались одиночные действия, можно также вызвать последовательность действий.

В таком случае указанные действия будут выполняться одно за другим, и если предыдущее действие выполнилось неудачно (ошибка), то все последующие действия не выполняются.

Если действие привело к ошибке, то все предыдущие действия не отменяются.

Мульти действие
<button xmlns="http://n2oapp.net/framework/config/schema/page-4.0">
<!-- Копируем данные в источник данных ds2 -->
<copy source-model="resolve" source-datasource="ds" target-datasource="ds2" target-model="resolve"/>
<!-- Сохраняем данные источника ds2 -->
<submit datasource="ds2"/>
<!-- Открываем страницу page -->
<open-page page-id="page" route="/open"/>
</page>

Абсолютно аналогичным образом работает определение мульти действия на странице или в виджете.

Мульти действие на странице
<page xmlns="http://n2oapp.net/framework/config/schema/page-4.0">
...
<actions>
<!-- Указываем id действия -->
<action id="multiSave">
<invoke operation-id="saveDocument"/>
<invoke operation-id="savePersonInfo"/>
</action>
</actions>

<toolbar>
<!-- Обращаемся к действию по его id -->
<button label="Сохранить данные страницы" action-id="multiSave"/>
</toolbar>
</page>
note

При использовании мульти действий существует одно естественное ограничение. Действие открытия страницы или окна завершает цепочку, а значит все действия, расположенные после него не будут выполнены.

Условный оператор if-else для действий

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

Оператор if-else работает по общепринятым правилам:

  • если выражение test в элементе <if> верно, то выполняется действие внутри элемента <if>
  • иначе проверяется выражение test в элементе <else-if>, и если оно верно то выполняется действие внутри него
  • если все предыдущие проверки были ложны, то выполняется действие внутри элемента <else>

Ограничений на количество элементов <else-if> нет.

Оператор if-else для действий
<button>
<!-- Выполняем операцию и получаем ответ -->
<invoke operation-id="saveInfo"/>

<!-- код ответа равен 1: сообщение об успехе -->
<if test="responseCode == 1">
<alert text="Действие выполнено успешно" color="success"/>
</if>
<!-- код ответа равен 2: сообщение о неудаче -->
<else-if test="responseCode == 2">
<alert text="Произошла ошибка" color="danger"/>
</else-if>
<!-- иначе: повторяем операцию -->
<else>
<invoke operation-id="saveInfo"/>
</else>
</button>
note

Оператор if-else действий может содержать внутри себя оператор if-else, переключатель switch/case и прочие действия.

Подробнее об операторе if-else для действий

Переключатель действий switch/case

Существует возможность использовать более упрощенную версию if-else - оператор switch/case. Он позволяет сопоставлять значение атрибута value элемента <case> со значением поля, указанного в атрибуте value-field-id элемента <switch>.

  • если совпадение найдено, то будет выполнено действие или последовательность действий, указанная в теле элемента <case>
  • если совпадений нет, то будет выполнено действие из элемента <default>
Переключатель действий switch/case
<button>
<switch value-field-id="document.type">
<case value="1">
<show-modal page-id="passport" page-name="Страница паспорта"/>
</case>
<case value="2">
<show-modal page-id="inn" page-name="Страница ИНН"/>
</case>
<default>
<open-page page-id="unknown_document" page-name="Страница заполнения документа"/>
</default>
</switch>
</button>
note

Переключатель действий switch/case может содержать внутри себя оператор if-else, переключатель switch/case и прочие действия.

Подробнее о переключателе действий switch/case