Обработка потери контекста данных
Glossary Item Box
Общие сведения
Механизм, отслеживающий потерю контекста данных на странице редактирования записи, позволяет при переходе со страницы, например, в другой раздел, автоматически определять наличие изменений. Если изменения вносились, то пользователь будет предупрежден о наличии несохраненных изменений и сможет вернуться к редактированию или покинуть страницу без сохранения (рис. 1).
Рис. 1. — Предупреждение о возможной потере изменений
Состав механизма отслеживания потери контекста данных на странице
В состав механизма отслеживания потери контекста данных на странице входят:
- Новые методы и события базового компонента Terrasoft.Component.
- Миксин CheckModuleDestroyMixin.
- Новые и измененные методы базовой страницы редактирования BasePageV2.
Новые методы и события базового компонента Terrasoft.Component
Метод canExecute()
Метод canExecute() вызывает событие canExecute, в параметры которого передает callback-функцию — ссылку на метод onClick(), внутри которого был вызван метод canExecute(). В свою очередь событие canExecute связывается с моделью представления и вызывает метод canBeDestroyed() миксина CheckModuleDestroyMixin. Этот метод может вернуть false в случае присутствия несохраненных данных на странице редактирования. Если все данные сохранены, то метод всегда возвращает true, соответственно, выполнение onСlick() не прерывается. Реализация метода canExecute():
// Генерирует событие canExecute. // Возвращает true, если можно продолжить выполнение метода onClick(). canExecute: function(config) { var args = config.args; var event = args[args.length - 1]; // Если метод onClick() был вызван из миксина CheckModuleDestroyMixin как callback-функция, // то в него последним параметром передается событие, которое сигнализирует о прерывании выполнения. if (event && event.isComeBack) { return true; } // Добавление в аргументы события прерывания выполнения метода. // Необходимо для остановки выполнения метода при вызове onСlick из callback-функции. Array.prototype.push.call(config.args, { isComeBack: true }); // Применение текущего контекста. Ext.apply(config, { scope: this }); // Генерация события canExecute. var canExecute = this.fireEvent("canExecute", config); return canExecute; },
Вызов метода canExecute() происходит в методе onClick() некоторых элементов управления или в других методах, вызываемых в onClick(). К таким элементам управления относятся базовая кнопка Terrasoft.Button, реестр Terrasoft.Grid, элементы меню Terrasoft.BaseMenuItem и др. При необходимости вызов этого метода может быть добавлен и для остальных компонентов. Пример вызова метода canExecute() в компоненте Terrasoft.Grid:
// Метод указания активной записи реестра. setActiveRow: function(newId) { var oldId = this.activeRow; if (!oldId && !newId) { return; } if (newId !== oldId) { var canExecute = oldId && this.canExecute({ method: this.setActiveRow, args: arguments }); // Если CheckModuleDestroyMixin вернул false, то выполнение метода прерывается. if (canExecute === false) { return; } ... } },
После клика на экземпляр класса Terrasoft.Grid вызывается метод-обработчик OnGridClick(), который в свою очередь вызывает метод setActiveRow(). В методе setActiveRow(), в случае если существует активная строка, вызывается метод canExecute(). В качестве аргумента методу canExecute() передается конфигурационный объект, в свойства которого добавляется ссылка на метод setActiveRow() и аргументы, с которыми был вызван setActiveRow(). В случае если вызванное событие canExecute вернет false, то работа метода setActiveRow() прервется. Однако, вызов метода setActiveRow() можно восстановить, т. к. он был передан в качестве callback-функции.
Событие canExecute
Событие canExecute объявлено в конструкторе базового компонента Terrasoft.Component, а его генерация происходит в методе canExecute():
// Конструктор класса. constructor: function(config) { this.addEvents( ... "canExecute" ); ... }
Для того чтобы управлять поведением компонента в конфигурационной схеме, необходимо связать модель представления с событием canExecute. Для этого в массиве модификаций diff базовой схемы раздела BaseSectionV2, в элементе DataGrid определяется привязка события canExecute к методу canBeDestroyed. Метод canBeDestroyed определен в миксине CheckModuleDestroyMixin.
// Массив модификаций базовой схемы раздела. diff: [ // Добавление элемента реестра. { "operation": "insert", "name": "DataGrid", "parentName": "DataGridContainer", "propertyName": "items", "values": { ... "canExecute": {"bindTo": "canBeDestroyed"}, ... } }...
Миксин CheckModuleDestroyMixin
Миксин CheckModuleDestroyMixin обеспечивает обмен сообщениями с открытыми страницами редактирования ( в том числе с открытыми в цепочке). Также он обеспечивает возможность прерывания выполнения метода, вызвавшего canExecute(), например, метода onClick() кнопки. Данный миксин "подмешивается" в представление модели конфигурационной схемы.
Обмен сообщениями с отрктытыми страницами редактирования обеспечивается методом updateCanBeDestroyedConfig():
// Обновляет информацию о возможности удаления контекста страниц редактирования. updateCanBeDestroyedConfig: function() { // Создание ключа. var cacheKey = this.Ext.String.format("{0}-cache", this.sandbox.id); // Сохранение в клиентский кеш по ключу объекта, с которым буду работать карточки. this.Terrasoft.ClientPageSessionCache.setItem(cacheKey, { canBeDestroyed: true }); // Публикация системного broadcast-сообщения. this.sandbox.publish("CanBeDestroyed", cacheKey); // Обновление результата работы подписчиков на сообщение. this.canBeDestroyedConfig = this.Terrasoft.ClientPageSessionCache.getItem(cacheKey); }
Отображение диалога с сообщением от страницы редактирования и обработка результата выбора пользователя реализованы в методе showCanBeDestroyed():
// Отображает сообщение в диалоге showCanBeDestroyed: function(resumeConfig) { // Сообщение от страницы, которое будет показано в диалоге подтверждения. var message = this.getDestroyedMessage(); // Отображение диалога подтверждения. this.Terrasoft.showConfirmation(message, function(returnCode) { // Если пользователь нажал "Да", то вызывается callback-функция. // Таким образом продолжается выполнение прерванного обработчика события клика по компоненту. if (returnCode === this.Terrasoft.MessageBoxButtons.YES.returnCode) { this.Ext.callback(resumeConfig.method, resumeConfig.scope || this, resumeConfig.args); } }, ["yes", "no"], this); }
Новые и измененные методы базовой страницы редактирования BasePageV2
Подписка на сообщение CanBeDestroyed, рассылаемое миксином CheckModuleDestroyMixin, реализуется в методе subscribeSandboxEvents():
// Подписка на сообщения. subscribeSandboxEvents: function() { ... this.sandbox.subscribe("CanBeDestroyed", this.onCanBeDestroyed, this); ... }
Проверка существования несохраненных данных осуществляется методами onCanBeDestroyed() и setNotBeDestroyedConfig():
// Проверяет существование несохраненных данных. onCanBeDestroyed: function(cacheKey) { // Получение и проверка объекта из кеша. var config = this.Terrasoft.ClientPageSessionCache.getItem(cacheKey); if (!this.Ext.isObject(config)) { return; } var isChanged = this.isChanged(); // Если страница редактирования имеет несохраненные данные, то формируется сообщение и изменяется объект в кэше. if (isChanged) { this.setNotBeDestroyedConfig(config); } }, ... // Формирует конфигурационный объект для вывода сообщения пользователю. setNotBeDestroyedConfig: function(config) { // Определение сообщения, которое будет показано пользователю. var message = this.get("Resources.Strings.PageContainsUnsavedChanges"); Ext.apply(config, { // Признак несохраненных данных. canBeDestroyed: false, // Сообщение, которое будет показано пользователю. errorInfo: { message: message } }); }