Подписка на изменение полей и дочерней коллекции

Материал из Lexema.ru
Перейти к: навигация, поиск

Связь между элементами управления экранной формы и данными в Lexema.ru осуществляется при помощи библиотеки Knockout.js. Благодаря этому может быть осуществлена подписка на изменение значений отдельных полей модели, а так же состава дочерней коллекции (добавления и удаления её строк). Программный код подписки, как правило, размещается в обработчике открытия экранной формы (Created), работа с которым подробно описана в соответствующем разделе статьи руководства.

Подписка на изменение значения поля

Подписка осуществляется с помощью метода subscribe observable-объекта поля модели. Общий синтаксис подписки:

L8.Data.root.ИМЯ_ПОЛЯ.subscribe(function(newValue) {
    console.log("Новое значение поля: " + newValue);
});

Если требуется выполнить скрипт обработчика ДО смены значения, необходимо подписаться в режиме beforeChange:

L8.Data.root.ИМЯ_ПОЛЯ.subscribe(function(oldValue) {
    alert("Старое значение перед изменением: " + oldValue);
}, null, "beforeChange");

Для одного поля (observable-объект) может быть добавлено несколько обработчиков.

Важно! В API Lexema.ru реализована обёртка над методом subscribe для подписки на изменение значения поля - метод valueChanged. Данный способ является более предпочтительным, т.к. позволяет абстрагироваться от используемой библиотеки Knockout.js. Синтаксис его использования практически такой же:

L8.Data.root.ИМЯ_ПОЛЯ.valueChanged(function(newValue) {
    console.log("Новое значение поля: " + newValue);
});

Перед написанием кода подписки в обработчике открытия формы (Created) целесообразно отладить его в консоли. Для этого откройте форму, в которой необходимо реализовать подписку. Откройте консоль разработчика (F12), введите код обработчика. После этого смените значение в целевом поле, отследите результат. Например, для формы расходов демонстрационного модуля "Домашняя бухгалтерия" может быть добавлен следующий обработчик изменения поля "Цена" (Price):

_lxDebug.currentState.L8.Data.root.Price.valueChanged(function(newValue) {
    console.log("Новое значение цены: ", newValue);
    alert("Новое значение цены: " + newValue);
});

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

SubscribeObservableDemo.png

Процесс добавления кода обработчика в метод Created подробнее описан в разделе " Пример создания обработчика" ниже в данной статье.

Процесс подписки на изменение observable-объектов описан в разделе "Explicitly subscribing to observables" официальной документации Knockout.js.

Следует отметить, что подписка средствами Knockout.js не является единственным способом реакции на изменение значения поля. Например, можно создать обработчик на изменение содержимого элемента управления формы (текстового поля, списка и т.п.), этот способ описан в соответствующем разделе статьи руководства. Наиболее предпочтительным способом подписки является использование обработчиков изменения полей модели, этот способ описан в соответствующем разделе статьи руководства.

Подписка на изменение состава дочерней коллекции

Данный механизм позволяет реагировать на события добавления и удаления строк в дочерней коллекции документа. Например, при добавлении новой записи могут быть инициализированы какие-то поля этой записи (например, сгенерирован номер документа). При удалении записи, так же, как и при добавлении, могут быть пересчитаны какие-то итоговые значения, например суммарная стоимость позиций в дочерней коллекции.

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

L8.Data.root.ИМЯ_ДОЧЕРНЕЙ_КОЛЛЕКЦИИ.subscribeArrayChanged({
    add: function(addedItem) {
        // код обработчика добавления элемента
        // addedItem - добавляемая запись. Для доступа к её полям следует писать:
        // addedItem.ИМЯ_ПОЛЯ() - для считывания значения. Например, addedItem.VCode()
        // addedItem.ИМЯ_ПОЛЯ(НОВОЕ_ЗНАЧЕНИЕ) - для изменения значения. Например, addedItem.DocumentNumber(789);
    }, 
    remove: function(removedItem) { 
        // код обработчика удаления элемента
        // removedItem - удаляемая запись
    }
});

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

Пример создания обработчика

В моделлере приложения из реестра экранный форм откройте для редактирования форму (например, OutgoingTransactionForm). Для получения названия объекта дочерней коллекции необходимо открыть соответствующую модель - на панели инструментов нажмите кнопку "Связанные документы", выберите из списка пункт "Перейти в модель":

OpenLinkedModel.png

В окне редактирования модели перейдите на вкладку "Дочерние таблицы", запомните имя требуемой дочерней коллекции (в данном случае - Detail):

ViewChildCollectionName.png

Вернитесь в окно редактирования экранной формы. Перейдите на вкладку "События". Если события Created нет в списке, то необходимо добавить его - выберите из списка "Тип события" пункт Created. Нажмите кнопку "Редактор" в строке Created:

OpenCreatedFormHandler.png

В редакторе введите код обработчика добавления и удаления записей дочерней коллекции, например:

L8.Data.root.Detail.subscribeArrayChanged({
    add: function(addedItem) {
        alert("В дочернюю коллекцию добавлен элемент с кодом " + addedItem.VCode());
    }, 
    remove: function(removedItem) { 
        alert("Удалена запись с наименованием " + removedItem.Product().Name);
    }
});

Сохраните и закройте редактор. Если обработчик Created был добавлен только сейчас, необходимо сохранить также и экранную форму. Перейдите в окно приложения в браузере, откройте экранную форму. Если она уже была открыта, необходимо обновить её с очисткой кеша (подробнее об этом см. в соответствующем разделе руководства. Для проверки работоспособности обработчиков добавьте и удалите записи дочерней коллекции:

ViewChildCollectionAddHandler.png

ViewChildCollectionRemoveHandler.png

См. также