angularjs - Proper way to pass functions to directive for execution in link -
i know pass functions directives via isolated scope:
.directive('mycomponent', function () { return { scope:{ foo: '&' } }; }) and in template can call function such:
<button class="btn" ng-click="foo({ myval: value })">submit</button> where myval name of parameter function foo in parent scope takes.
now if intend use link function instead of template, have call with: scope.foo()(value), since scope.foo serves wrapper of original function. seems bit tedious me.
if pass function mycomponent directive using =:
.directive('mycomponent', function () { return { scope:{ foo: '=' } }; }) then able use scope.foo(value) link function. valid use case use 2-way binding on functions, or doing sort of hack shouldn't doing?
here why downvoted answer.
first, should never use '=' pass function references directives.
'=' creates 2 watches , uses them ensure both directive scope , parent scope references same (two-way binding). bad idea allow directive change definition of function in parent scope, happens when use type of binding. also, watches should minimized - while work, 2 $watches unnecessary. not fine - part of down vote suggesting was.
second - answer misrepresents '&' does. & not "one way binding". gets misnomer because, unlike '=', not create $watches , changing value of property in directive scope not propagate parent.
according docs:
& or &attr - provides way execute expression in context of parent scope
when use & in directive, generates function returns value of expression evaluated against parent scope. expression not have function call. can valid angular expression. in addition, generated function takes object argument can override value of local variable found in expression.
to extend op's example, suppose parent uses directive in following way:
<my-component foo="go()"> in directive (template or link function), if call
foo({myval: 42}); what doing evaluating expression "go()", happens call function "go" on parent scope, passing no arguments.
alternatively,
<my-component foo="go(value)"> you evaluating expression "go(value)" on parent scope, calling $parent.go($parent.value)"
<my-component foo="go(myval)"> you evaluating expression "go(myval)", before expression evaluated, myval replaced 42, evaluated expression "go(42)".
<my-component foo="myval + value + go()"> in case, $scope.foo({myval: 42}) return result of:
42 + $parent.value + $parent.go() essentially, pattern allows directive "inject" variables consumer of directive can optionally use in foo expression.
you this:
<my-component foo="go"> and in directive:
$scope.foo()(42) $scope.foo() evaluate expression "go", return reference $parent.go function. call $parent.go(42). downside pattern error if expression not evaluate function.
the final reason down vote assertion ng-event directives use &. isn't case. none of built in directives create isolated scopes with:
scope:{ } the implementation of '&foo' (simplified clarity), boils down to:
$scope.foo = function(locals) { return $parse(attr.foo)($scope.$parent, locals); } the implementation of ng-click similar, (also simplified):
link: function(scope, elem, attr) { elem.on('click', function(evt) { $parse(attr.ngclick)(scope, { $event: evt } }); } so key remember when use '&', not passing function - passing expression. directive can result of expression @ time invoking generated function.
Comments
Post a Comment