I have a directive with a transcluded scope something like this:
<my-control>
Some Content: {{value}}
</my-control>
Where value
is coming from the parent scope.
I want to add a function that interacts with the control's scope, so I can do stuff like this:
<my-control>
Some Content: {{value}}
<button ng-click="$close()">Close</button>
</my-control>
Similar to the way ngRepeat
adds properties like $index
to the row scope. What is the easiest way to do this in my directive?
When we do not specify either scope:true
(new Scope) or scope:{}
(isolatedScope) and when we re-use the directive, the properties defined on the scope will be overridden.
For Ex:
<div ng-controller="AppCtrl">
<my-control name="myControl1">
Some Content: {{value}}
My Control Name: {{name}}
</my-control>
<my-control name="myControl2">
Some Content: {{value}}
My Control Name: {{name}}
</my-control>
</div>
Instead of printing both myControl1
and myControl2
on the screen, it will print myControl2
two times.
To overcome this issue try any of the below solutions.
Solution1
transclde:true
will create a new Scope. set the properties on this scope instead of the directive's scope.
app.directive('myControl', function() {
return {
restrict: 'E',
transclude: true,
template: '<div><p><strong>Welcome to the testMe directive!</strong></p> <div ng-transclude></div></div>',
link: function(scope, element, attrs) {
var transclusionTarget = element[0].querySelector('[ng-transclude]').firstChild;
var transclusionScope = angular.element(transclusionTarget).scope();
transclusionScope.name = attrs.name;
}
}
});
here the element's under ng-transclude
div will be compiled with the transclusionScope, grab it and update the properties in it.
Solution2
Instead of using ng-transclude
, manually transclude the content.
app.directive('myControl', function() {
return {
restrict: 'E',
transclude: true,
template: '<div><p><strong>Welcome to the testMe directive!</strong></p> <div transclude-target></div></div>',
link: function(scope, element, attrs, directiveCtrl, transcludeFn ) {
var transclusionScope = scope.$new(),
transclusionTarget = element[0].querySelector('[transclude-target]');
transclusionScope.name = attrs.name;
transcludeFn(transclusionScope, function (clone) {
angular.element(transclusionTarget).append(clone);
});
}
}
});
Here, create a new Scope
extending the directive's scope using scope.$new()
. And update the properties in it.
Solution1 may not work in all the cases. By the time we access firstChild
and if it is not ready Solution1 will fail.
Solution2 is cleaner and will work in all the cases.