Bootstrap modal в Ember

Речь идет о Twitter Modal. С точки зрения Bootstrap’a, создание такого компонента не представляет сложной задачи (см. мануал по ссылке выше). А вот если хочется, чтоб доступ к нему был как к компоненту Ember’a — чтоб были свои view, шаблон?

Возьмем существующий набор элементов — Bootstrap for Ember. Все они базируются на основе Ember.Component. По ссылке есть небольшое руководство по использованию bs-modal. Там есть пример с обычным модал-окном, с модал-окном, которое создается программно из контроллера, а так же confirm-modal. Однако, в мануале нет ни слова о FooterViews или о том, как самому создать modal и добавить его в Bootstrap.ModalManager. Да, если нужен небольшой modal с каким-то сообщением для пользователя (пусть и со сложной разметкой), то этих примеров хватит с головой (главное, не перепутать, что передевать в ModalManager.open — view или template):

App.SomeController = Em.ObjectController.extend({
 
	actions: {
 
		firstAction: function() {
			Bootstrap.ModalManager.open(
				"my-modal-1",
				'First Modal Title',
				App.MyFirstView,
				[
					Ember.Object.create({title: Em.I18n.t('common.cancel'), clicked:"modalCanceled", dismiss: 'modal'}),
					Ember.Object.create({title: Em.I18n.t('ok'), clicked:"modalConfirmed", type:'success'})
				],
				this
			);
		},
 
		secondAction: function() {
			Bootstrap.ModalManager.open(
				"my-modal-2",
				'Second Modal Title',
				'templates/mySecondModal',
				[
					Ember.Object.create({title: Em.I18n.t('common.cancel'), clicked:"modalCanceled", dismiss: 'modal'}),
					Ember.Object.create({title: Em.I18n.t('ok'), clicked:"modalConfirmed", type:'success'})
				],
				this
			);
		}
 
	}
 
});

В firstAction в open третьим параметром передается view, а в secondAction — шаблон. Об этом надо помнить.

А если задача стоИт более сложная? Если, к примеру, надо в теле modal-а сделать чекбокс, который будет активировать кнопку «Ok». Другими словами, делается double-confirmation-modal — пользователь нажимает на кнопку, ему выводится окно с сообщением типа «а вы уверены, что хотите выполнить это действие?» и при этом кнопка «Ok» не активна, пока пользователь не кликнет на чекбокс:

Double Confirmation Popup

Создать такой modal используя Bootstrap.ModalManager.open не получится, так как повесить disabledBinding (в виде какого-то флага в контроллере) на нужную кнопку не получится. Сноска: кнопки передаются 4-м параметром в метод open. Почему не получится? Потому что кнопки вставляются в шаблон modal’a таким образом, что игнорируют такой биндинг. Придется копнуть немного глубже — в сторону FooterViews и «самостоятельного» создания modal’a.

Если посмотреть исходник BS.ModalManager, то видно, как в методе open создается окно. Никто не мешает нам взять этот фрагмент и использовать его в нужных нам целях. А цель у нас простая — не пользоваться «фасадным» методом open и иметь доступ к создаваемому modal’у:

App.SomeController = Em.ObjectController.extend({
 
	confirmChecked: false,  // checkbox value
 
	destroyButtonEnabled: Ember.computed.not('confirmChecked'), // inversed value used on button binding
 
	actions: {
 
		firstAction: function() {
			var modalComponent = this.container.lookup('component-lookup:main').
				lookupFactory('bs-modal', this.get('container')).create();
		}
 
	}
 
});

Теперь можем задавать любые нужные нам свойства созданного окна:

modalComponent.setProperties({
      name: 'my-modal',
      title: 'My title',
      manual: true,
      targetObject: this,
      body: App.DestroyPopupView,
      controller: this,
      footerViews: [App.DestroyPopupFooterView]
    });

targetObject — объект, куда будут переданы action от кнопок. Сами кнопки находятся в App.DestroyPopupFooterView. Вот ее код:

App.DestroyAppPopupFooterView = Ember.View.extend({
 
  targetObjectBinding: 'controller',
 
  templateName: 'myPopup',
 
  destroyButton: Em.Object.create({title: 'Да, clicked: "modalConfirmed", type:'success'}),
 
  cancelButton: Em.Object.create({title: 'Нет', clicked: "modalCanceled"})
 
});

Шаблон view с кнопками представлен ниже. bs-button — это компонент кнопки. Описание по ссылке.

{{bs-button
  content=view.cancelButton
  targetObjectBinding="view.targetObject"
}}
 
{{bs-button
  content=view.destroyButton
  disabledBinding="controller.destroyButtonEnabled"
  targetObjectBinding="view.targetObject"
}}

Шаблона тела modal’s

<p class="alert alert-danger"> <span class="icon-warning-sign"></span>  Большое сообщение о не восполнимом вреде выполняемого действия.</p>
{{input type="checkbox" checkedBinding="controller.confirmChecked"}} Вы точно хотите это сделать??

Сейчас объект modal’a создан, но не вставлен на страницу. Для этого надо выполнить такое:

Bootstrap.ModalManager.register('my-modal', modalComponent);

Метод register выполняет добавление окна в менеджер (чтоб его потом можно было удалить) и вставляет modal на страницу (выполняет appendTo в корневой элемент targetObject’a). Если же нам надо было бы просто добавить окно в менеджер, то использовали бы метод add. По ссылке дан исходник modalManager’a, где видно, что еще есть методы close, remove, hide, show, toggle. Все их можно использовать для изменения состояния нужного modal’a.

Вернемся к нашему окну. Изначально кнопка «Да» не активна. При клике на чекбокс срабатывает биндинг на confirmChecked. Из-за него меняется destroyButtonEnabled, который «активирует» кнопку. modalConfirmed и modalCanceled должны быть описаны в actions контроллера.

Живая демка на jsFiddle.

, , , , ,

Оставить комментарий

Top ↑ | Main page | Back