AngularJS: трансляция событий из директивы - программирование
Подтвердить что ты не робот

AngularJS: трансляция событий из директивы

Я видел, как люди делали это из любого места в своем коде:

$rootScope.$broadcast('someEvent', someParameter); 

а затем в каком-то контроллере:

$rootScope.$on('someEvent', function(event, e){ /* implementation here */ });

Теперь, я хотел бы broacast событие из директивы. Хорошая практика - транслировать его на уровне rootScope? Я хотел бы обработать это событие в контроллере. Могу ли я использовать $scope, или мне еще нужно слушать на $rootScope?

4b9b3361

Ответ 1

В моем случае я просто хочу передать событие из директивы в контроллер представления, в котором я использую директиву. Есть ли смысл использовать трансляцию?

Я хотел бы, чтобы директива вызывала метод на контроллере, который указан в HTML, где используется директива:

Для директивы, которая использует изолированную область:

<div my-dir ctrl-fn="someCtrlFn(arg1)"></div>

app.directive('myDir', function() {
  return {
    scope: { ctrlFn: '&' },
    link: function(scope, element, attrs) {
       ...
       scope.ctrlFn({arg1: someValue});
    }

Для директивы, которая не использует изолированную область:

<div my-dir ctrl-fn="someCtrlFn(arg1)"></div>

app.directive('myDir', function($parse) {
  return {
    scope: true,  // or no new scope -- i.e., remove this line
    link: function(scope, element, attrs) {
       var invoker = $parse(attrs.ctrlFn);
       ...
       invoker(scope, {arg1: someValue} );
    }

Ответ 3

Вот пример TypeScript того, как вызвать метод на контроллере из встроенной директивы. Самое главное отметить, что имя параметра директивы для вашего обратного вызова использует a и когда определено, и при вызове этого обратного вызова вы не должны использовать позиционные параметры, а вместо этого используете объект со свойствами, имеющими имена параметров в целевом объекте.

Зарегистрируйте директиву при создании своего модуля приложения:

module MyApp {
    var app: angular.IModule = angular.module("MyApp");
    MyApp.Directives.FileUploader.register(app);
}

Код регистрации выглядит следующим образом:

module MyApp.Directives.FileUploader {
  class FileUploaderDirective implements angular.IDirective {
      public restrict: string = "E";
      public templateUrl: string = "/app/Directives/FileUploader/FileUploaderDirective.html";

      //IMPORTANT - Use & to identify this as a method reference
      public scope: any = {
        onFileItemClicked: "&"
      };
      public controller: string = "MyApp.Directives.FileUploader.Controller";
      public controllerAs: string = "controller";
      public bindToController: boolean = true;
      public transclude: boolean = true;
      public replace: boolean = true;
  }

  export function register(app: angular.IModule) {
      app.controller("MyApp.Directives.FileUploader.Controller", Controller);
      app.directive("fileUploader", () => new FileUploaderDirective());
  }
}

Контроллер директивы будет выглядеть следующим образом

module MyApp.Directives.FileUploader {
    export class Controller {
        public files: string[] = ["One", "Two", "Three"];
        //The callback specified in the view that created this directive instance
        public onFileItemClicked: (fileItem) => void;

        // This is the controller method called from its HTML ng-click
        public fileItemClicked(fileItem) {
            //IMPORTANT: Don't use comma separated parameters,
            //instead use an object with property names to act as named parameters
            this.onFileItemClicked({
                fileItem: fileItem
            });
        }
    }
}

Директива HTML выглядит примерно так:

<ul>
  <li ng-repeat="item in controller.files" ng-click="controller.fileItemClicked (item)">
    {{ item }}
  </li>
</ul>

В главном представлении будет экземпляр вашей директивы, например:

<body ng-app="MyApp" ng-controller="MainController as controller">
  <file-uploader on-file-item-clicked="controller.fileItemClicked(fileItem)"/>
</body>

Теперь все, что вам нужно на вашем MainController, это метод

public fileItemClicked(fileItem) {
  alert("Clicked " + fileItem);
}