Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angularjs: broadcast from directive to controller

Im trying to send a message from within a directive to its parent controller (without success)

Here is my HTML

<div ng-controller="Ctrl">
   <my-elem/>
</div>

Here is the code in the controller which listens for the event

$scope.on('go', function(){ .... }) ;

And finally the directive looks like

angular.module('App').directive('myElem',
   function () {
    return {
        restrict: 'E',
        templateUrl: '/views/my-elem.html',
        link: function ($scope, $element, $attrs) {
            $element.on('click', function() {
                  console.log("We're in") ; 
                  $scope.$emit('go', { nr: 10 }) ;
            }
        }
    }
  }) ;

I've tried different scope configuration and $broadcast instead of $emit. I see that the event gets fired, but the controller does not receive a 'go' event. Any suggestions ?

like image 546
Jeanluca Scaljeri Avatar asked Sep 25 '13 10:09

Jeanluca Scaljeri


People also ask

How pass data from directive to controller in AngularJS?

isolatedBindingFoo:'=bindingFoo' can pass the data from directive to controller. or you can use service. Before you down vote someone you are welcome to ask it first if you don't understand.

What is $parent in AngularJS?

$scope.$parent refers to the $scope of the parent element. E.g. if you have an element with a controller nested within another element with it's own controller: <div ng-controller="parentController"> ...

What is attrs in AngularJS?

scope is an AngularJS scope object. element is the jqLite-wrapped element that this directive matches. attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values. controller is the directive's required controller instance(s) or its own controller (if any).


2 Answers

$broadcast, $emit, and $on are deprecated

Use of the scope/rootScope event bus is deprecated and will make migration to Angular 2+ more difficult.

To facilitate making the transition to Angular 2+ easier, AngularJS 1.5 introduced components:

app.component("myElem", {
    bindings: {
      onGo: '&',
    },
    template: `
        <button ng-click="$ctrl.go($event,{nr:10})">
            Click to GO
        </button>
    `,
    controller: function() {
        this.go = (event,data) => {
            this.onGo({$event: event, $data: data});
        };
    }
});

Usage:

<div ng-controller="Ctrl as $ctrl">
   <my-elem on-go="$ctrl.fn($data)></my-elem>
</div>

The component uses an attribute with AngularJS expression (&) binding that invokes a function in the parent controller. Instead of clogging the scope/rootScope event bus with numerous events, the event goes directly to the function that uses it.

The DEMO

angular.module('app', [])
.controller ('Ctrl', function () {
    this.go = (data) => {
      console.log(data);
      this.update = data;
    };
})
.component("myElem", {
    bindings: {
      onGo: '&',
    },
    template: `
      <fieldset>
        <input ng-model="$ctrl.nr" /><br>
        <button ng-click="$ctrl.go($event,$ctrl.nr)">
            Click to Update
        </button>
      </fieldset>
    `,
    controller: function() {
        this.nr = 10;
        this.go = (event,data) => {
            this.onGo({$event: event, $data: data});
        };
    }
})
<script  src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="Ctrl as $ctrl">
    <p>update={{$ctrl.update}}</p>
    <my-elem on-go="$ctrl.go($data)"></my-elem>
</body>

For more information, see

  • AngularJS Developer Guide - Component-based application architecture
like image 106
georgeawg Avatar answered Oct 14 '22 07:10

georgeawg


There is no method on with scope. In angular it's $on

below should work for you

<!doctype html>
<html ng-app="test">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.js"></script>

  </head>
 <body ng-controller="test" >    
 <my-elem/>

<!-- tabs -->


 <script>
     var app = angular.module('test', []);
     app.controller('test', function ($scope) {

         $scope.$on('go', function () { alert('event is clicked') });
     });
     app.directive('myElem',
   function () {
       return {
           restrict: 'E',
           replace:true,
           template: '<div><input type="button" value=check/></input>',
           link: function ($scope, $element, $attrs) {
               alert("123");
               $element.bind('click', function () {
                   console.log("We're in");
                   $scope.$emit('go');
               });
               }
       }
   }) ;

   </script>
</body>


</html>
like image 25
Ajay Beniwal Avatar answered Oct 14 '22 07:10

Ajay Beniwal