Добрый день.
Вожусь с AngularJS. Документацию почитал, теперь руку набиваю на примерах из реальной жизни в сцепке с Yii
Собственно, пример:
Есть две директивы — форма и модальное окно. Форма представляет собой обертку над ActiveForm из Yii.
Форма может как существовать сама по себе, так и быть вложена в модальное окно:
<modal-dialog><br>
<active-form><br>
</active-form><br>
</modal-dialog><br>
Модальный диалог умеет обрабатывать событие нажатия на кнопку подтверждения. Форма умеет делать валидацию на сервере и получать результаты валидации в виде события.
Хочется, чтобы модальный диалог мог уведомить форму о том, что его подтвердили, а форма, в свою очередь, могла попросить диалог закрыться, например. При этом форма должна оставаться рабочей, будучи сама по себе, без модального диалога.
Испробовав несколько подходов остановился на использовании require в директиве:
angular.module('app').directive 'activeForm', (yiiscripts) -><br>
scope: 'isolated'<br>
replace: false<br>
transclude: false<br>
require: ['activeForm','?^modalDialog']<br>
controller: ($scope, $element) -><br>
onSubmit: ($form, modalDialogController) -><br>
modalDialogController.startLoading() if modalDialogController<br>
$element.submit()<br>
afterValidate: ($form,data,hasErrors,modalDialogController) -><br>
modalDialogController.endLoading() if modalDialogController<br>
modalDialogController.close() if !hasErrors and modalDialogController<br>
!hasErrors<br><br>
link: ($scope, element, attrs, controllers) -><br>
[myController, modalDialogController] = controllers<br>
yiiscripts.activeform element.attr('id'),<br>
afterValidate: ($form, data, hasErrors) -><br>
myController.afterValidate($form,data,hasErrors,modalDialogController)<br><br>
if modalDialogController and modalDialogController.listenSubmit<br>
modalDialogController.listenSubmit -><br>
myController.onSubmit(element, modalDialogController)<br>
angular.module('app').directive 'modalDialog', (templates) -><br>
scope:<br>
title: '@modalTitle'<br>
modalOk: '@modalOk'<br>
modalCancel: '@modalCancel'<br>
replace: true<br>
transclude: true<br>
template: $('#modal_dialog_template').html()<br>
controller: ($scope) -><br>
submitListeners = []<br>
controller =<br>
listenSubmit: (listener) -><br>
submitListeners.push(listener)<br>
onSubmit: (evt) -><br>
evt.preventDefault()<br>
$.each submitListeners, -> this.apply(evt)<br>
startLoading: -><br>
$scope.$broadcast('startLoading')<br>
endLoading: -><br>
$scope.$broadcast('endLoading')<br>
close: -><br>
$scope.$broadcast('close')<br>
controller<br><br>
link: ($scope, element, attrs, controller) -><br><br>
element.css({display:'block'})<br>
.modal(show: false)<br>
$scope.$on 'close', -> element.modal('hide')<br>
$scope.$on 'startLoading', -> element.modal('loading')<br>
$scope.$on 'endLoading', -> element.modal('loading')<br>
$('input[type="submit"]',element).click(controller.onSubmit)<br>
Форма при линковке запрашивает контроллер модального диалога выше по иерархии, если он есть (require ["?^modalDialog"])
Если он есть, то добавляется в подписчики на сообщение о сабмите диалога.
Когда получает сообщение о сабмите, ставит диалог в состояние загрузки и запускает сабмит непосредственно формы.
После валидации на сервере срабатывает сообщение onAfterValidate, где мы отменяем для диалога состояние загрузки данных и дальше стандартно для Yii-формы.
Все работает как хотелось, в том числе и для формы в отдельности. Хотелось бы узнать, насколько данный подход вписывается в гайды разработки на AngularJS. Я пытался задействовать $scope.$emit, $scope.$broadcast для обмена сообщениями между директивами (форма делает $scope.$emit на свои события, диалог $scope.$broadcast на свои), но для директив мне нужен isolated scope и в этом случае $scope формы не является дочерним по отношению к $scope диалога, соответственно сообщения ходят мимо.
Заранее спасибо.