4

In AngularJS we can broadcast, and listen for events:

$rootScope.$emit('myEvent',$scope.data);

$rootScope.$on('myEvent', function(event, data) {}

Is there any way to listen for events inside a component?

What I want to achieve is to execute some action on set of components which are repeated inside a form. Ng-repeat iterates over some model of course. Some data from the model is bound to the component. It's easy to bind function to component, so component can execute some logic, but the opposite direction doesn't seem to be so easy.

<div ng-repeat="someObject in mainModel.listOfObjects">
   <someControl ng-model="someObject.foo"></someControl>
   <custom-component ng-model="someObject.bar"></custom-component>
</div>
<someButton ng-click="executeActionOnAllCustomComponents()">
1

3 Answers 3

5

I think your best bet is keep using the standard event emitting with $emit() and $broadcast(). angular 1.5 introduced some new hooks and sintax but inside a component you can always inject $rootScope and $scope, and handling any event as you were used to in angular < 1.5.

Template:

<div ng-controller="parentController">
 <div ng-repeat="someObject in mainModel.listOfObjects">
   <someControl ng-model="someObject.foo"></someControl>
   <custom-component ng-model="someObject.bar"></custom-component>
 </div>
</div>

Parent controller:

angular.controller('parentController', ['$scope', function($scope){
 ..
 if(somethingHappend)
   $scope.$broadcast('event.sample', {}); //down in the scope chain
})

Component:

angular.component('customComponent', {
 bindings: {
  ngModel: '<' //one-way binding
 },
 controller: MyCtrl
}
MyCtrl.$inject = ['$scope', '$rootScope'];

function MyCtrl('$scope', $rootScope){
 ..
 $scope.$on('event.sample', function(evt, data){
  //do your logic
 }


}

Another option, if you want to check for changes on your model (made from the othe parent scope, supposing a one-way binding on your scope variables), is to use the hook $doCheck which is triggered each digest cycle, as opposed to the old watch mechanism you must save your old value and compare it to the new one.

var self = this;
var oldModel = angular.copy(self.ngModel);
self.$doCheck = function(){
 if(self.model !== oldModel){
   //do something
 }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Great answer, grazie mille Karim!
0

You can pass $event as parameter to function

please see the below code.

<span ng-click=get($event)> click !!</span>

 $scope.get=function(ev)
{
alert(ev);
};

Result will be [object MouseEvent]

Comments

0

You can use RxJS in the Angular 2+ style:

'use strict';

    import {from, fromEventPattern} from 'rxjs';
    import {map, tap, switchMap, distinctUntilChanged} from 'rxjs/operators';

    export default {
        bindings: {},
        controller: function (SomeService, $rootScope) {
            const self = this;

            self.$onInit = () => {
                fromEventPattern(
                    (handler) => $rootScope.$on('@some-event', handler)
                ).pipe(
                    distinctUntilChanged((x, y) => _.isEqual(x, y)),
                    switchMap(([e, data]) => from(SomeService.getSomething()))
                ).subscribe(
                    data => console.log(data),
                    error => console.log(error)
                );

            };
        },
        templateUrl: './some-component.html'
    }

So the trick is to use fromEventPattern to create Observable from AngularJS event listener:

fromEventPattern(
   (handler) => $rootScope.$on('@some-event', handler)
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.