Reputation: 2185
That title is a mouth-full! I've got some code written by another developer that's on leave and is unavailable to explain himself. None of us left in the office can figure out why it works. Any help would be appreciated!
We have a number of directives that use the results of a function defined in the controller as one of the properties. The method on the controller looks something like this.
$scope.required = function(pathString, object){
/*
pathString is a string representation pointing to a property in object
object is
Returns true/false for the property described
in the path string and the state of the object.
*/
}
Usually, when we use that as a property value for a directive implementation in an html file it looks like this.
<normal-directive
isrequired='required("Path.to.property", object)'></normal-directive>
The weird directive is unremarkable in their declaration. It's definition is identical to the normal directives.
directive('weirdDirective', function(){
return {
restrict: 'E',
scope: {
required: '&isrequired'
},
templateUrl: 'path/to/template'
}
});
The weirdness is in the implementation. Instead of the string and object passed to the function in the normal directives, these two new variable fieldpath and item appear.
<weird-directive
isrequired='required(fieldpath, item)'></weird-directive>
The variables fieldpath and item do not appear anywhere in the controller or the weird directive declaration. They are, however, present in the weird directive template, shown below.
<div class='weird-directive'>
<normal-directive
isrequired='required({fieldpath:'Path.to.property', item: object})'></normal-directive>
</div>
This raises ALL KINDS of questions for me. I thought the call to required was executed in the parent scope, so I don't understand how it's using variables that appear to be assigned a value in the template. Furthermore, objects are usually passed as a single argument, but they appear to have been split out here to provide the required two arguments.
I would very much like to understand how this works, so any help or explanation would be most appreciated!
Upvotes: 0
Views: 658
Reputation: 8642
"I thought the call to required was executed in the parent scope"
correct, the function is evaluated in the parent scope.
"so I don't understand how it's using variables that appear to be assigned a value in the template"
Not exactly, what happening is slightly different.
Let's examine the DDO.
return {
restrict: 'E',
scope: {
required: '&isrequired'
},
templateUrl: 'path/to/template'
}
and the function in the parent scope:
$scope.required = function(pathString, object){
}
the &
symbol means passing a reference to a function that, as you mentioned, is evalueted in the parent scope, however the documentation explain that if the method requires some parameters, you must pass along with the function the name of these parameters:
<weird-directive
isrequired='required(fieldpath, item)'></weird-directive>
I understand that the syntax could be a little misleading, but here we're not invoking the function, we are specifying that fieldpath
and item
are keys that will be used later during the invocation phase.
Now inside your child scope, you can invoke the function passing as an argument a map, where each key represent a parameter name, and the correspondent value the value itself.
in your case:
<normal-directive
isrequired='required({fieldpath:'Path.to.property', item: object})'></normal-directive>
last but not least, the evaluation of the function happens only after the evaluation of the parameters.
hope this helps.
Upvotes: 1