Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$emit vs callback in parent child directive communication best approach

Im trying to understand what is the best GENERIC approach to communicate between parent and child directive with isolated scopes (they might be reusable items).

meaning if child directive needs to update parent directive in some manner (both have isolated scopes), should I pass a callback function :

e.g:

.directive('filterReviewStepBox', function () {
    return {
        restrict: 'EA',
        scop: {
            //some data
        },
        template: '<div>text<reusable-dir></reusable-dir call-back="foo"></div>',
        link: function (scope, elem, attrs) {
            scope.foo = function () {
                console.log('bar');
            };
        }
    };
}).directive('reusableDir', function () {
    return {
        restrict: 'EA',
        scope: {
            callBack: '=callBack'
                //other data
        },
        template: '<div>text<button type="button" ng-click="bar"></button></div>',
        link: function (scope, elem, attrs) {
            scope.bar = function () {
                scope.callBack();
            }
        }
    };
});

or should I use $emit():

e.g:

  directive('filterReviewStepBox', function () {
        return {
            restrict: 'EA',
            scope: {
                // some data
            },
            template: '<div>text<reusable-dir></reusable-dir></div>',
            link: function (scope, elem, attrs) {
                scope.$on('foo', function () {
                    console.log('bar');
                });
            }
        };
    }).directive('reusableDir', function () {
        return {
            restrict: 'EA',
            scope: { //some data
            },
            template: '<div>text<button type="button" ng-click="bar"></button></div>',
            link: function (scope, elem, attrs) {
                scope.bar = function () {
                    scope.$emit('foo');
                };
            }
        };
    });

I feel that emit would be easier to understand on a larger scale but worried about performance and overhead, but Im still unsure

tried looking for the best approach online but Im still stomped

EDIT

I forgot about the

require

option. but I'm still not sure this is the most correct solution. Since this doesn't allow me to reuse the child or grandchild and kind of makes the directive a single purpose item.

like image 997
Jony-Y Avatar asked Oct 24 '15 08:10

Jony-Y


Video Answer


1 Answers

For this purpose the best is to utilize "require" attribute.

Complete guide to directives tell us this about require attribute : https://docs.angularjs.org/api/ng/service/$compile

Require another directive and inject its controller as the fourth argument to the linking function. The require takes a string name (or array of strings) of the directive(s) to pass in.

Require just tells the directive it should look for some parent directive and take its controller. You can tell directive to search in parent elements with ^ prefix and tell if this requirement is optional with ? prefix.

I have modified your example, so reusableDir can call filterReviewStepBox controller, but can be also used alone.

http://jsbin.com/gedaximeko/edit?html,js,console,output

angular.module('stackApp', [])  
.directive('filterReviewStepBox', function () {
        return {
            restrict: 'EA',
            scope: {
                // some data
            },
            template: '<div>text<reusable-dir></reusable-dir></div>',
            link: function (scope, elem, attrs) {

            },
            controller : function() {
              this.notify = function(value) {
                console.log('Notified : ' + value);
              };              
            },
            controllerAs: 'vm',
            bindToController: true
        };
    }).directive('reusableDir', function () {
        return {
            restrict: 'EA',
            scope: { //some data
            },
            require: '?^filterReviewStepBox',
            template: '<div>text<button type="button" ng-click="bar()"></button></div>',
            link: function (scope, elem, attrs, controller) {
                scope.bar = function () {
                  if (controller) {
                    controller.notify('foo');
                  }
                };
            }
        };
    });
like image 144
Víťa Plšek - angular.cz Avatar answered Oct 13 '22 00:10

Víťa Plšek - angular.cz