snaggs
snaggs

Reputation: 5713

Fail to catch event when call directive method from controller in Angular

I try to call directive method from controller by using $broadcast.

But I catch event only if press on button twice.

See Demo in Plunker

Do I miss something?

Here is snippets of code:

HTML

<div ng-controller="MainCtrl">
    <test-dir name="{{test}}"></test-dir>

    <select ng-model="broadcastTo" ng-options="x as x for x in ['test1', 'test2', 'test3']"></select>
    <button ng-click="broadcastToSelectedChild()">test</button>
  </div>

JS

var app = angular.module('angularjs-starter', []);

app.controller('MainCtrl', function($scope) {



  // a method that broadcasts to a selected child.
  $scope.broadcastToSelectedChild = function (){
    $scope.test = $scope.broadcastTo;

    console.log('call-' + $scope.test);

    $scope.$broadcast('call-' + $scope.test);
  };
});

app.directive('testDir', function (){
  return {
    restrict: 'E',
    scope: {
      'name': '@'
    },
    template: '<div>{{name}} called: {{called}}</div>',
    link: function(scope, elem, attr) {

      scope.called = false;



      //set up the name to be used as the listened to event.
      var eventOn;
      scope.$watch('name', function(v) {
        console.log('listen ..','call-' + scope.name);
        if(eventOn){
          eventOn();
        }
        eventOn = scope.$on('call-' + scope.name, function (){
            alert(scope.name);
          });
      });
    }
  };
});

Took example from: HERE

Thanks,

Upvotes: 0

Views: 315

Answers (1)

Khanh TO
Khanh TO

Reputation: 48982

It does not work because you bind your directive scope's name to your controller scope's test, but ng-model on the <select> binds to broadcastTo. When you select a value from the <select>, test is not updated and $watch inside your directive does not fire to attach the event handler.

Try:

<test-dir name="{{broadcastTo}}"></test-dir>

DEMO

In your code, you have to click twice because the first click updates test and causes $watch to fire to attach the event handler:

$scope.test = $scope.broadcastTo;

And the second click will be able to handle the event broadcast from your controller.

Upvotes: 1

Related Questions