I wish to alias a model used in a template such that the same template can be reused for different models. For instance in the following model:
member = {
name: "Member1",
children:[
{
name:"Child1"
},
{
name:"Child2"
}
]
}
both "member" and "children" have "name" property. So I wish to create a single template manipulating this "name" property. I was able to achieve this with the help of this question:
Bind ngInclude to different models
As suggested, I created a directive such as:
app.directive('member', function(){
return {
restrict: 'A',
template: "{{prefix}}<input type='text' ng-model='member.name'>",
scope: {
member: "="
}
};
});
Following is the usage of this directive:
<div ng-controller="MemberCtrl">
{{member | json}}
<div member="member"></div>
<div member="member.children[0]"></div>
</div>
I was able to achieve the template reuse, however since I'm using "scope" in my directive, this has created an isolated scope which is not able to access any property of the controller scope. So for the controller:
app.controller('MemberCtrl', function($scope){
$scope.member = {
name: "Member1",
children:[
{
name:"Child1"
},
{
name:"Child2"
}
]
};
$scope.prefix = "Mr.";
});
the template inside the directive is not able to access the "prefix" property. Following is the jsfiddle:
http://jsfiddle.net/vaibhavgupta007/mVBaC/1/
What could be the issue in this?
Edit
I can also use $parent to access the prefix. But is this clean approach.
Just define 'prefix' as isolated scope variable in your directive definition object, and reference it in element attributes.
app.directive('member', function(){
return {
restrict: 'A',
template: "{{prefix}}<input type='text' ng-model='member.name'>",
scope: {
member: "=",
prefix: "="
}
};
});
<div ng-controller="MemberCtrl">
{{member | json}}
<div member="member" prefix="prefix"></div>
<div member="member.children[0]" prefix="prefix"></div>
</div>
To be able to bind a directive scope property to various controller properties (e.g., member and member.children[0]) for use in a generic template, I believe you will need to use the isolate scope syntax (as you already discovered).
Once you go down the "isolate scope road", you'll have to specify all controller properties and functions that your directive needs access to as additional attributes:
<div member="member" prefix="{{prefix}}" join-fn="joinNameWithPrefix(someName)"></div>
Then in your directive:
template: "{{prefix}}<input type='text' ng-model='member.name'>"
+ "<br>fn result={{ joinFn( {someName: member.name} ) }}",
scope: {
member: "=",
prefix: '@',
joinFn: '&'
},
Use = for two-way databinding, @ for one-way strings, and & for one-way expressions.