this, подписка на событие в separated и combined режимах.
Прошу у коллективного разума помощи в объяснении происходящего.
Юзкейс:
Верхнее горизонтальное меню. Карточка "Обращения" добавить кнопку-выпадающий список, пункты которого, фактически будут инициировать создание нового Email (активности) с разными входными параметрами и настройками фильтрации в нем относительно полей "Кому", "От кого" и.т.
Предпринятые действия: Уже ставшая обыденной проблема того что карточка может быть открыта в 2-х режимах: "Combined" и "Separated", т.е. это фактически разные схемы, а как следствие модели в текущем окружении.
1) Чтобы по 2 раза не дублировать логику создадим миксин-модуль, и соберем в нем всю необходимую функциональность: метод объявляющий пункты меню, методы-обработчики непосредственно для пунктов меню, вспомогательные методы (н/п метод помогающий получить Id текущей карточки вне зависимости от текущего режима, определяющий его по косвенным признакам и workAreaMode и соответственно получающий или this.get("Id") или this.get("ActiveRow"), или восстанавливающий его из HistoryState, или даже получающие его через "GridData" если все остальные способы не сработали)
2) Выделим в отдельный модуль - наши события, чтобы их собственно 2-ды не определять в карточках карточки и секции, в последних в свою очередь предусмотрим при инициализации карточки - регистрацию событий из объекта зависимости, при помощи this.sandbox.registerMessages, в Миксине объявим метод осуществляющий подписки на события и в схеме карточки и раздела при инициализации вызовем этот метод.
3) У "Обращения" уже предусмотрена деталь "Email", само собой нам надо будет либо вызывать карточку Email (EmailPageV2) из своего кода через openCardInChain и далее реализовывать регистрацию в детали сообщения самостоятельно, или же использовать уже готовую логику детали, и вызывать ее штатный addRecord() метод - что гораздо проще и лаконичнее.
4) Создаем замещающую схему детали в котором подписываемся на событие которое генерирую наши пункты меню, в колбэке-подписчике просто вызываем addRecord(); метод.
...Пока что все получает очень просто.
5) Далее пунктов меню 3-шт. у каждого своя "смысловая нагрузка", стало быть нам требуется организовать логику позволяющую определить какой из пунктов вызвал наш addRecord, для этого в замещающей схеме EmailPageV2 мы при инициализации генерируем событие-запрос и подписываемся на событие-ответ, на которое предварительно установлен подписчик в наших схемах карточки или секции (не важно, так как подписчики вызываются идентично из Миксина), обработчик которого в свою очередь генерирует событие-ответ, и уже в этом событии и передает все необходимые данные, в том числе и "нажатый пункт меню".
И вот тут нас поджидает сюрприз:
Для того чтобы сохранить статус (какой пункт нажат) перед вызовом события - которое инициирует в детали addRecord (это кстати косвено приводит нас к потере окружения, т.к. метод addRecord мы не контролируем лишь знаем что в конечном итоге он откроет EmailPageV2).
Так вот, сохраним значение в текущей модели - this.set("myState", myStateStringIdentifier);
Логика такова: раз наша подписка на событие-запрос осуществленная при инициализации схемы (карточки или секции) т.е. к this, а стало быть к модели, то коллбэк-обработчик которому передать при подписке this вторым аргументом будет выполняться в его окружении, а стало бы с той-же моделью, т.е. в нем можно будет получить сохраненное значение через this.get("myState").
Но это не так... Вся цепочка отлично отрабатывает в случае страницы открытой в Separate режиме - вообще без изъянов.
А вот с Combined режимом получается вот какое поведение:
замещающая схема CaseSection
"onEntityInitialized": function() {
this.callParent(arguments);
this.AskQuestionMixinSUBSRIBER(this);
document.scope = this;
},
"init": function() {
this.callParent(arguments);
this.sandbox.registerMessages(AksQuestionMessages.messages);
this.initAskQuestionMenuCollection();
}
},
AskQuestionMixinSUBSRIBER - метод объявленный в миксин-модуле
this.sandbox.subscribe(
"AskQuestionEmailTypeRequest",
function() {
this.sandbox.publish(
"AskQuestionEmailTypeResponse",
{askType: this.get("askType")},
["AskQuestion_from_Case_" + this.getCaseID()]
);
},
scope,
["AskQuestion_from_Case_" + this.getCaseID()]
);
}
Обработка пункта меню приводит к сохранению состояния в this.set("askType", askType)
Но коллбек будучи выполненным из Combined режима - все равно теряет окружение, несмотря на то, что во время подписки ему явно передали "scope"
Т.е. когда он выполняется - this.get("askType") // undefined
Чего кстати не происходит в Sepated режиме.
PS: Пока что я решил вопрос через расширение глобального window.Terrasoft объекта своим свойством в котором сохраняю "askType". Но по мне это "не очень решение".
Нравится
Здравствуйте, Илья.
Более простым решением будет:
1) Заместить в секции метод initQueryColumns - для подтягивания в GridData колонок, которые есть в карточке, однако не выведены в реестр.
2) При нажатии на кнопки выпадающего меню вызывать метод openCardInChain. Данный метод позволяет не только открывать карточку, а и передавать значения в атрибуты открывшейся карточки. Получать значения необходимо основываясь на режиме карточки.
Пример openCardInChain с передачей значений атрибутов:
this.openCardInChain({ schemaName: "EmailPageV2", operation: "add", moduleId: "00000000-0000-0000-0000-000000000000", defaultValues: [{name: "atr1", value: "value 1"}, {name: "atr2", value: "value2"}] });
про openCardInChain и преимущества этого подхода, мне известно.
А вот про
1) Заместить в секции метод initQueryColumns - для подтягивания в GridData колонок, которые есть в карточке, однако не выведены в реестр.
Хотелось бы попросить Вас написать еще пару слов, просто чтобы понимать возможности системы, может в исходных кодах какой либо конфигурации можно посмотреть юзкейз.
Я так понимаю этот метод принимает объект ESQ-запроса на исполнение, т.е. именно он и фактически получает данные в модель - так ?
Я не много не понимаю назначения метода и как с ним положено работать.
PS: у каждого окружения есть "Backbone.Model" - this.model обладающий уникальным cid, можно ли как-то обращаться к конкретной загруженной модели с заведомо известным cid ? или получить модель из БД зная ее идентификатор ?
Метод initQueryColumns по сути принимает esq, которое и будет вытаскивать данные в раздел. В базовой реализации данный метод добавляет к esq базовые колонки (первичная для отображения колонка итд), а также колонки, выведенные в грид.
Для того, чтобы в GridData присутствовали дополнительные колонки - необходимо заместить метод примерно следующим образом:
initQueryColumns: function(esq) { this.callParent(arguments); esq.addColumn("DayType.NonWorking"); esq.addColumn("Test"); },
В итоге получить значения в секции можно кодом:
var a = activeRow.get("DayType.NonWorking"); var b = activeRow.get("Test");
activeRow.get("DayType.NonWorking");
я так понимаю через this.get() ?
Или activeRow это какой-то особенный объект ?
activeRow это элемент текущей (выделенной) строки.
var activeRow = this.getActiveRow(); var b = activeRow.get("Test");
activeRow насколько я понимаю присутствует только когда карточка открыта в Combined режиме ?
Это свойство самого грида, как в реестре раздела, реестре детали так и в комбинированном режиме.