Окна и диалоги

Всплывающее окно — это абсолютно спозиционированный элемент в DOM-дереве. Никакой другой логики контрол в себе не несет. Он не знает о своей позиции, окружении и шаблоне, который отрисовывает.

Для открытия всплывающего окна используют подходящий опенер, который определяет позиционирование самого окна и его конфигурацию.

В этом разделе вы найдете типы окон и их опенеры.

Общая схема конфигурации

Рис. 1. Схема взаимодействия контрола с всплывающими окнами.

Примеры, иллюстрирующие конфигурацию, взяты из примера конфигурации диалогового окна.

Прямого доступа к Popup нет, это приватный контрол. Для того, чтобы повлиять на поведение окна, нужно правильно задать конфигурацию.

Добавление открывающего контрола в шаблон

На этом этапе в вёрстку родительского компонента (компонента, из которого планируется открывать всплывающее окно) нужно добавить открывающий контрол или Opener.

Opener открывает всплывающее окно Popup, реагируя на событие родительского контрола MyComponent.

Для организации взаимодействия сo всплывающим окном, требуется добавить Opener в вёрстку MyComponent.

Далее для контрола Opener нужно задать конфигурацию. Список общих опций приведён в таблице.

НазваниеОписание
nameИмя открывающего контрола. Используется в обработчике открытия всплывающего окна.
templateШаблон всплывающего окна.
templateOptionsСобственные опции, передаваемые в шаблон. Опция актуальна, когда задан собственный шаблон template.

Остальные опции описаны в API класса конкретного контрола.

Для диалога подтверждения конфигурация передается только динамически — через метод open().

Пример 1. Шаблон MyComponent.wml.

<Controls.popup:Dialog name="dialog" template="Examples/Popup/templates/dialog" />

Создание шаблона всплывающего окна

Внешний вид отображаемого всплывающего окна определяется его шаблоном.

В создаваемых шаблонах подключаются стандартные шаблоны с базовой раскладкой. На их основе строится вёрстка всплывающих окон. В шаблонах определены позиции с изменяемым контентом.

Пример 2. Ниже показано содержимое шаблона Examples/Popup/templates/dialog.tmpl. Опции шаблона передаются через templateOptions.

<Controls.popupTemplate:Dialog headingCaption="Создание категории">
   <ws:headerContentTemplate>
      ...
   </ws:headerContentTemplate>
   <ws:bodyContentTemplate>
      ... 
   </ws:bodyContentTemplate>
</Controls.popupTemplate:Dialog>

Пример 3. Передача пользовательской опции type в шаблон всплывающего окна Examples/Popup/TestDialog.

<Controls.popupTemplate:Dialog headingCaption="PopupManager">
   <ws:headerContentTemplate>
      <div>
         <Controls.buttons:Button caption="Закрыть {{_options.type}}" on:click="_close()"/>
      </div>
   </ws:headerContentTemplate>
   <ws:bodyContentTemplate>
      ...
   </ws:bodyContentTemplate>
</Controls.popupTemplate:Dialog>

Значение опции type передано в Controls.popup:Dialog через templateOptions.

<Controls.popup:Dialog name="modalDialog" modal="{{true}}" template="Controls-demo/Popup/TestDialog">
   <ws:templateOptions type="dialog"/>
</Controls.popup:Dialog>

Создание обработчика, открывающего окно

Необходимо определить событие контрола MyComponent. В нашем примере всплывающее окно открывается при клике по кнопке. Она добавлена в вёрстку контрола рядом с открывающим контролом. На клик кнопки создан обработчик, вызывающий метод openDialog().

  • WML
    <Controls.popup:Dialog name="dialog"  />
    <Controls.buttons:Button name="dialogButton" caption="Диалог" on:click="openDialog()"/>
  • JavaScript
    openDialog: function () {
        
       // this._children содержит экземпляры дочерних контролов.
       // Обращение к экземпляру производится через имя дочернего контрола.
        
       // Метод open() откроет всплывающий элемент.
       // В аргументах метода можно передать объект с настройками контрола.
       this._children.modalDialog.open();
    },

Подробнее об отладке открытия окон и панелей можно прочитать здесь

Событие открытия всплывающего окна

При открытии любого всплывающего окна опенер оповещает о событии open. Чтобы на такое событие задать обработчик, выполните следующие действия:

  1. Откройте wml-файл, где описан опенер. Например, в контексте настоящей статьи мы назвали этот файл MyComponent.wml.
  2. Согласно синтаксису подписки на события, передайте опенеру атрибут on:open с именем функции-обработчика.
    <Controls.popup:Dialog
        name="notification"
        on:open="_notifyOpenHandler()">
        ...
    </Controls.popup:Dialog>
  3. Откройте JS-модуль контрола, например в настоящей статье это MyComponent.js, и опишите функцию-обработчик.
    _notifyOpenHandler: function () {
        // Прикладной код, обрабатывающий открытие окна.
        ...
    },

Создание обработчика, закрывающего окно

Базовая раскладка всплывающего окна содержит крестик, по клику на который окно будет закрываться по умолчанию. Для особых сценариев необходимо создать обработчик, закрывающий окно.

Обработчик можно создать со стороны всплывающего окна.

  • WML. В шаблон добавлена кнопка Controls/buttons:Button, по клику на которую окно должно закрыться.
    <Controls.buttons:Button caption="Закрыть" on:click="_close()" />
  • JavaScript
    _close: function (){
       // Оповещаем о событии.
       this._notify('close', [], {bubbling: true});
    },

Обработчик можно создать со стороны родительского контрола, открывшего это окно. Для этого достаточно вызывать метод close() у открывающего контрола.

  • JavaScript
    // this._children содержит экземпляры дочерних контролов.
    // Обращение к экземпляру производится через имя дочернего контрола.
     
    this._children.stack.close();

Событие о закрытии всплывающего окна

При закрытии любого всплывающего окна опенер оповещает о событии close. Чтобы на это событие задать обработчик, выполните следующее:

  1. Откройте WML-шаблон, где описан опенер. Например, в контексте настоящей статьи мы назвали этот файл MyComponent.wml.
  2. Согласно синтаксису подписки на события, передайте опенеру атрибут on:close с именем функции-обработчика.
    <Controls.popup:Dialog
        name="notification"
        on:close="_notifyCloseHandler()">
        ...
    </Controls.popup:Dialog>
  3. Откройте JS-модуль контрола. Например, в настоящей статье это файл MyComponent.js. В модуле опишите функцию-обработчик.
    _notifyCloseHandler: function () {
        // Прикладной код, обрабатывающий закрытие окна.
        ...
    },

Передача данных из всплывающего элемента в родительский контрол. Событие sendResult.

В отдельных случаях необходимо передать данные из всплывающего элемента в родительский контрол.

Используем обработчики событий. В случае всплывающего окна нас интересует событие sendResult.

В родительском контроле опишем функцию-обработчик для события result, которая выполнится, когда всплывающее окно оповестит о событии sendResult. Количество аргументов обработчиков (а также — типы их значений) зависит от конкретной реализации всплывающего окна.

Например, для опенера "Окна выбора из справочника" тип возвращаемого значения зависит от количества выбранных элементов коллекции:

  • RecordSet — для одного выбранного элемента, для нескольких элементов, выбранных из одной вкладки;

  • IList — для выбора нескольких элементов из разных вкладок.

  1. В родительском контроле.
    • в верстке открывающего контрола в опции всплывающего окна добавлен обработчик:
      <Controls.popup:Stack name="stack"
          on:result="_notifyResultHandler()"
          template="My/Template/For/Stack" />
    • JavaScript
      _notifyResultHandler: function (event, result) {
         if (result) {
            alert(result);
         }
      }
  2. В шаблоне всплывающего окна.
    • WML
      <Controls.buttons:Button caption="Сохранить" on:click="_onClick()"/>
    • JavaScript
      _onClick: function (){
         this._notify(
            'sendResult',
            // Передаем результат. 
            [... , ... ],
            {bubbling: true}
         );
      }

Типовые проблемы при работе со всплывающими окнами

Демонстрационный пример