AMar4enko
@AMar4enko

AngularJS: способы взаимодействия директив — emit, broadcast, controller require?

Добрый день.

Вожусь с 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 диалога, соответственно сообщения ходят мимо.



Заранее спасибо.
  • Вопрос задан
  • 11048 просмотров
Пригласить эксперта
Ответы на вопрос 2
EugeneOZ
@EugeneOZ
Вполне вписывается (подробнее: www.egghead.io/video/rzMrBIVuxgM), только вот
template: $('#modal_dialog_template').html()

не вписывается :) Имхо, лучше в script такие шаблоны подгружать, чтобы небыло зависимости от jQuery.
Ответ написан
RodgerFox
@RodgerFox
Прям для вас: https://egghead.io/lessons/angularjs-directive-to-...
Извините за год ожидания =D
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы