Отслеживание изменений сущностей
Для отслеживания изменений сущности существует механизм подписки (listen), который, в зависимости от своих параметров, использует одну из двух реализаций:
- Подписка на события изменения сущности (ADD, SET, REMOVE)
- Подписка на канал событий, связанных с сущностями
Подписка на события изменения сущности
Реализация этого механизма предполагает уведомление фронтенда об изменениях сущности через ответ сервера, который будет доступен только на той странице, на которой был сделан запрос к бэкенду. Все примеры, перечисленные ниже, относятся как раз к этой ситуации.
Например, если при сохранении формы в модальном окне нужно обновить инпуты в родительской форме или обновить список объектов сущности, если вы изменили или добавили новую.
Случай 1
Бывают случаи, когда у вас есть форма создания/редактирования объекта и в ней есть инпут с выбором объекта другого типа. Например: вы добавляете товар и выбираете его категорию, а если категории нет, то вы хотите прямо здесь ее создать.
В этом случае у инпута выбора категории нужно добавить кнопку создания объекта через "addObjectButton" и добавить прослушку событий по объектам указаного типа через "listen" чтобы после создания объект появлвлся в выпадающем списке.
На форме, где у вас будет инпут обязательно добавьте секции:
- attrs.addObjectButton
- listen
{
"id": "mylego",
"name": "me-lego",
"elems": [
{
"id": "ex_access_id",
"name": "me-input",
"entityId": 2830,
"attrs": {
"type": "select", // говорим, что у нас выпадающий селектбокс
"required": true,
"addObjectButton": { // говорим, что у нас есть кнопка создания объектов указанного entity_id
"env": {
"sp": { // если вам нужно перезать что-то на страницу создания объекта, при нажатии на кнопку создания объекта сделайте это тут
"obj": {
"mode": "feed",
"ex_system_id": "google_adwords"
}
}
},
"title": "Подключить аккаунт"
}
},
"listen": [
{
// Тут мы гвоорим, что хотим отслеживать изменения сущности при операция добавление и изменения
"code": [
"ADD",
"SET"
],
"entityId": 2830,
"refreshRefPvmData": {}, // Говорим, что хотим обновлять список опшенов me-input
"objectId": 0
}
],
// Это просто для полноценности примера
"label": "Укажите аккаунт для получения данных или добавьте новый",
"refPvmData": {
"id": "$metaql",
"sp": {
// Кстати, это хороший пример использования защищенного языка запросов к данным. Это не полноценный SQL
// Тут работает общий ACL и нет ничего, кроме простых SELECT запросов
"dbQuery": {
"command": "SELECT id,name FROM meta.ex_access WHERE ex_system_id = 'google_adwords' and user_status='ENABLED' ORDER BY name"
}
}
}
}
]
}
Случай 2
Или у вас есть список объектов какой-либо сущности в таблице и при редактировании или добавлении объекта в модальном окне вы хотите перезагружать данные таблицы
Для таблицы добавляется атрибут listen
- code: укажите на какие коды вы подписываетесь ADD, SET, REMOVE
- entityId: укажите id сущности, которую будете прослушивать
- reload: говорит, что надо сделать reload страницы при получении уведомления об изменении данных
<script type="meta/sql" order="400" id="res" entity-id="2830" db-alias="meta" entity-id="ex_system"
listen='[{"code": ["ADD", "REMOVE", "SET"], "reload":{},"entityId": "2830"}]'
...
На стороне модального окна
На стороне страницы создания/редактирования объекта сущности нужно обязательно залогировать добавление или изменение вызовом ObjectLogService.logValue. Эти данные пойдут в лог и смогут быть использованы для подписки на события через артрибут listen
<script type="meta/js" elem="hidden" states="save">
function main(pvm, vm, env, ObjectLogService) {
var isNew = false;
var objectId = env.object_id;
pvm.toInitialState();
pvm.closeModal();
pvm.changeState('default');
pvm.popup = {level: "success", message: "${i18n('common.saveSuccess')}"};
ObjectLogService.logValue(env.entityId, objectId, isNew ? 'ADD' : 'SET', env.sp.obj);
}
</script>
Подписка на канал событий
Это более общий случай использования уведомлений об изменении объектов. Он позволяет обрабатывать события в других окнах браузера и реализует отправку событий через сокеты (PubSubService).
Также, именно эта реализация позволяет уведомлять об изменении объектов не только текущее, но и остальные открытые пользователем окна браузера с Метой.
Пример:
<script type="meta/sql" order="400" id="res" entity-id="2830" db-alias="meta" entity-id="ex_system"
listen='[{"pubSubChannel": ["ObjectLogService"], "reload":{},"entityId": "2830", "objectId": "12"}]'
...
В данном примере мы подписываемся на события в канале ObjectLogService, которые будут связаны с определенным entityId и objectId. При этом objectId - необязательный параметр, можно подписываться на события всех объектов сущности.
ObjectLogService - зарезервированный канал, используемый сервисом ObjectLogService, который, кроме отправки сообщений об изменении объектов в Шину, отправляет также пользователю, инициировавшему изменение объекта сообщение через PubSubService.
PubSubService можно также вызвать самостоятельно, например:
<script type="meta/js" elem="hidden" states="save">
function main(pvm, vm, env, PubSubService) {
PubSubService.pubToUserChannel(env.user_id, 'page', 'c16649d7-866b-47d9-a61c-0370596cd575', 'test_channel', {});
}
</script>
Подобный код вызвал бы срабатывание слушателя, настроенного следующим образом:
<script type="meta/sql" order="400" id="res" entity-id="2830" db-alias="meta" entity-id="ex_system"
listen='[{"pubSubChannel": ["test_channel"], "reload":{},"entityId": "page", "objectId": "c16649d7-866b-47d9-a61c-0370596cd575"}]'
...