Авторазмеры контролов
Часто отображение одного контрола зависит от размеров другого, связанного с ним.
Например, полоса прокрутки появляется/уходит с изменением высоты списка. То есть, контейнер списка должен каким-то образом узнавать про изменение высоты списка, чтобы отрисовать или спрятать полосу прокрутки. Таким образом, в задаче изменения размеров и отображения можно выделить два вида контролов.
Контрол-инициатор изменяет собственный размер и, тем самым, инициирует изменение отображения контролов, которые вовлечены в этот процесс. Далее на схемах контрол-инициатор обозначен как ResizeInitiatorControl
.
Контрол-наблюдатель отслеживает возможный процесс изменения размера у контрола-инициатора. Определенным образом контрол-наблюдатель должен быть оповещён о происшедших изменениях контрола-инициатора и перестроиться соответствующим образом. Далее на схемах контрол-наблюдатель обозначен как ResizeObserverControl
.
В зависимости от уровня вложенности контрола-инициатора
, задача изменения размеров и отображения контролов на странице укладывается в реализацию двух возможных схем.
Схема 1. Контрол-инициатор находится на некотором уровне вложенности контрола-наблюдателя
Пример
Изменение размеров списка (контрол-инициатор
) влечёт изменение в отображении и в размерах полосы прокрутки в контейнера такого списка (контрол-наблюдатель
).
Рис. 1. Списочный контрол является контрол-инициатором. Контейнер списочного контрола является контролом-наблюдателем.
Решение
- В этом случае
контрол-инициатор
оповещаетконтролы-наблюдатели
об изменении размеров. Для этого публикуется всплываемое событие controlResize.// TypeScript protected _afterRender(): void { this._notify('controlResize', [], {bubbling: true}); }
- В
контролах-наблюдателях
, которые должны отреагировать на событиеcontrolResize
, создаются обработчики события.<!-- WML --> <MyControl on:controlResize="_myHandler()" />
Рис. 2. Оповещение и обработка события controlResize.
Реализация в платформенных контролах
Описанный механизм по умолчанию внедрен в следующих платформенных контролах.
Оповещают о событии | Ожидают событие |
---|---|
Схема 2: контрол-наблюдатель находится на некотором уровне вложенности контрола-инициатора.
Пример
Документ (ResizeInitiatorControl
) изменил ширину, и, соответственно, изменилось отображение хлебных крошек (ResizeObserverControl
) в документе.
Рис. 3. Отображение хлебных крошек в зависимости от изменения ширины документа.
Решение
Рис. 4. Оповещение и обработка события controlResize.
- В
ResizeInitiatorControl
помещаем Controls/event:Register (далее по текстуRegister
) — контрол, регистрирующий все вложенные Controls/event:Listener (далее по текстуListener
) и генерирующий событие об изменении размеровResizeInitiatorControl
.- Внимание:
Listener
регистрируется только у ближайшегоRegister
. При создании собственногоRegister
убедитесь о своевременном оповещении зарегистрированныхListener
(см. п.7).
- Внимание:
- Для
Register
в опцию register передаём название генерируемого события, напримерcontrolResize
.
<!-- WML -->
<Controls.event:Register
register="controlResize" />
- Внутрь
Register
помещаемResizeObserverControl
. - В
ResizeObserverControl
помещаемListener
. - В
Listener
описываем обработчик события.
Например, на событиеcontrolResize
создаётся обработчик_myResizeHandler
.
<!-- WML -->
<Controls.event:Listener
event="controlResize"
on:controlResize="_myResizeHandler()" />
- Обработчик этого события объявляем в
ResizeObserverControl
.
// TypeScript
protected _myResizeHandler(event): void {
// Здесь прикладной разработчик пересчитываем размеры и меняет отображение ResizeObserverControl.
...
},
- В
ResizeInitiatorControl
создаём метод, напримерmyControlResize
, вызываемый каждый раз при изменении размеров самогоResizeInitiatorControl
. В методе дляRegister
вызываем start(), чтобы оповестить зарегистрированныеListener
.
// TypeScript
protected myControlResize(): void {
myRegister.start();
}
Реализация в платформенных контролах
Описанный механизм по умолчанию внедрен в следующих платформенных контролах.
Оповещают о событии | Ожидают событие |
---|---|
SbisEnvUI/Bootstrap при изменении окна браузера оповещает о событии все дочерние контролы, сверху вниз. Таким образом, если стоит задача подписки на событие изменения окна, можно использовать схему 2.