Independent scopes and function parameters
By using the local scope attribute, you can pass an external function parameter (for example, a function defined in the controller $ scope) to the instruction. These operations can be completed. The following is an example of defining a local scope attribute named add to save the reference of the input function:
Angular. module ('ctictivesmodule ')
. Directive ('isolatedscopewithcontroller', function (){
Return {
Restrict: 'EA ',
Scope :{
Datasource: '= ',
Add :'&',
},
Controller: function ($ scope ){
//...
$ Scope. addCustomer = function (){
// Call an external scope function
Var name = 'new Customer Added by ctive VE ';
$ Scope. add ();
// Add a new 'customer' to the command scope
$ Scope. customers. push ({
Name: name
});
};
},
Template: '<button ng-click = "addCustomer ()"> Change Data </button> <ul>
<Li ng-repeat = "cust in MERS" >{{ cust. name }}</li> </ul>'
};
});
The consumer of an instruction can pass an external function to the instruction by defining an add attribute. As follows:
<Div isolated-scope-with-controller datasource = "MERS" add = "addCustomer ()"> </div>
In this example, the addCustomer () function is called when you click the button created in the command. There is no parameter input, so this is a relatively simple operation.
How to pass parameters to the addCustomer () function? For example, assume that the addCustomer () function is displayed in the following controller and a name parameter needs to be passed to the command when the function is called:
Var app = angular. module ('ctictivesmodule', []);
App. controller ('customer', ['$ scope', function ($ scope ){
Var counter = 0;
$ Scope. customer = {
Name: 'David ',
Street: '1970 Anywhere St .'
};
$ Scope. customers = [];
$ Scope. addCustomer = function (name ){
Counter ++;
$ Scope. customers. push ({
Name: (name )? Name: 'new customer' + counter,
Street: counter + 'Cedar Point St .'
});
};
$ Scope. changeData = function (){
Counter ++;
$ Scope. customer = {
Name: 'James ',
Street: counter + 'Cedar Point St .'
};
};
}]);
Passing a parameter in a command to an external function is very simple after you understand how it works. Below are some of the methods that developers may try at first:
Angular. module ('ctictivesmodule ')
. Directive ('isolatedscopewithcontroller', function (){
Return {
Restrict: 'EA ',
Scope :{
Datasource: '= ',
Add :'&',
},
Controller: function ($ scope ){
...
$ Scope. addCustomer = function (){
// Call an external function. Note that a name parameter is directly passed here.
Var name = 'new Customer Added by ctive VE ';
$ Scope. add (name );
// Add a new 'customer'
$ Scope. customers. push ({
Name: name
});
};
},
Template: '<button ng-click = "addCustomer ()"> Change Data </button> <ul>' +
'<Li ng-repeat = "cust in MERS" >{{ cust. name }}</li> </ul>'
};
});
Note that the command controller tries to call an external function by calling $ scope. add (name) and passing a parameter. Can this work? In fact, the output of this parameter in the external function is undefined, which may make you have no idea why. So what should we do next?
Select 1: Use the object literal
One way is to pass an object literal. The following is an example of how to pass a name to an external function:
Angular. module ('ctictivesmodule ')
. Directive ('isolatedscopewithcontroller', function (){
Return {
Restrict: 'EA ',
Scope :{
Datasource: '= ',
Add :'&',
},
Controller: function ($ scope ){
...
$ Scope. addCustomer = function (){
// Call external functions
Var name = 'new Customer Added by ctive VE ';
$ Scope. add ({name: name });
// Add new customer to directive scope
$ Scope. customers. push ({
Name: name,
Street: counter + 'Main St .'
});
};
},
Template: '<button ng-click = "addCustomer ()"> Change Data </button>' +
'<Ul> <li ng-repeat = "cust in MERS" >{{ cust. name }}</li> </ul>'
};
});
Note that when calling the $ scope. add () method, an object literal is passed as a parameter. Unfortunately, it still cannot work! Why? The name attribute defined in the object literal volume passed to $ scope. add () also needs to be defined in the external function when assigned to the instruction. It is very important that the parameter name written in the view must match the name in the object literal. The following is an example:
<Div isolated-scope-with-controller datasource = "MERS" add = "addCustomer (name)"> </div>
We can see that when the command is used in the view, the addCustomer () method adds a parameter name. This name must match the name in the literal volume of the object passed in when $ scope. add () is called in the command. In this way, the command can work correctly.
Option 2: store a function reference and call it
The problem with the above method is that a parameter must be passed to a function when using commands, and the parameter name must be defined in the form of an object literal in the command. It will not work if any point does not match. Although this method can meet the requirements, there are still many problems. For example, if the instruction does not have a complete instruction document, it is difficult to know what the parameter name needs to be passed in the instruction. In this case, you have to go through the instruction source code to view the parameter content.
Another feasible method is to define a function on the instruction, but without parentheses after the function name, as shown below:
<Div isolated-scope-with-controller-passing-parameter2 datasource = "MERS" add = "addCustomer"> </div>
To pass parameters to the external addCustomer function, you need to do the following in the command. Put the $ scope. add () (name) code to the method that can be called by addCustomer:
Angular. module ('ctictivesmodule ')
. Directive ('isolatedscopewithcontrollerpassingparameter2', function (){
Return {
Restrict: 'EA ',
Scope :{
Datasource: '= ',
Add :'&',
},
Controller: function ($ scope ){
...
$ Scope. addCustomer = function (){
// Call external functions
Var name = 'new Customer Added by ctive VE ';
$ Scope. add () (name );
...
};
},
Template: '<button ng-click = "addCustomer ()"> Change Data </button> <ul>' +
'<Li ng-repeat = "cust in MERS" >{{ cust. name }}</li> </ul>'
};
});
Why does this method work? This should start with another major role. & In commands, AngularJS calculates the value of this expression and returns it when the controller calls the scope attribute defined in. For example, enter add = "x = 42 + 2" in the view, then read $ scope in the command. when adding (), the calculation result (44) of this expression is returned. Any valid AngularJS expression can be the value of the add attribute and be calculated when reading the add attribute. Therefore, when we enter the add = "MERS" function without parentheses in the view, $ scope in the command. add () actually returns the customers () function defined in the controller (). Therefore, calling $ scope. add () (name) in the command is equivalent to calling the controller's MERS (name ).
Output $ scope. add () in the command to get the following content (verify as mentioned above ):
& Operation mechanism
If you are interested in the & running mechanism, when & local scope attribute is called (for example, a dd local scope attribute in the preceding example), the following code will execute:
Case '&':
ParentGet = $ parse (attrs [attrName]);
IsolateScope [scopeName] = function (locals ){
Return parentGet (scope, locals );
};
Break;
The above attrName variable is equivalent to add in the local scope attribute of the command in the preceding example. The parentGet function returned by $ pares is called as follows:
Function (scope, locals ){
Var args = [];
Var context = contextGetter? ContextGetter (scope, locals): scope;
For (var I = 0; I <argsFn. length; I ++ ){
Args. push (argsFn [I] (scope, locals ));
}
Var fnPtr = fn (scope, locals, context) | noop;
EnsureSafeObject (context, parser. text );
EnsureSafeObject (fnPtr, parser. text );
// IE stupidity! (IE doesn' t have apply for some native functions)
Var v = fnPtr. apply
? FnPtr. apply (context, args)
: FnPtr (args [0], args [1], args [2], args [3], args [4]);
Return ensureSafeObject (v, parser. text );
}
Process the literal attribute of the code ing object to the external function parameter and call the function.
Although there is no need to understand how to use the local scope attribute, it is always interesting to explore what AngularJS has done behind it.
End
We can see from the above that the & parameter passing process is still a bit difficult. However, once you learn how to use it, the whole process is not too difficult to use.