I have this HTML with a span
element that specifies a directive:
<div ng-controller="MyCtrl">
<span id="theSpan" my-directive="{{data.one}}" title="{{data.two}}">
</div>
The directive appends some HTML to the element:
var myApp = angular.module('myApp', []);
myApp.directive('myDirective', function() {
return {
template: "<div>{{text}}</div>",
scope: {
text: "@myDirective"
}
};
});
function MyCtrl($scope) {
$scope.data = {
one: 'One!!',
two: 'Two!!'
};
}
This code results in the following DOM structure:
<div ng-controller="MyCtrl" class="ng-scope">
<span id="theSpan" my-directive="One!!" title="" class="ng-isolate-scope ng-scope">
<div class="ng-binding">One!!</div>
</span>
</div>
The problem is the missing data from the title
attribute on the span
. I can get it to work correctly by adding title: '@'
to the scope, like this:
myApp.directive('myDirective', function() {
return {
template: "<div>{{text}}</div>",
scope: {
text: "@myDirective",
title: '@' // <-- added
}
};
});
which results in this DOM:
<div ng-controller="MyCtrl" class="ng-scope">
<span id="theSpan" my-directive="One!!" title="Two!!" class="ng-isolate-scope ng-scope">
<div class="ng-binding">One!!</div>
</span>
</div>
How do I code my directive such that attributes on the element are preserved, without having to specify them in the directive's scope? (Perhaps a better question is: why isn't the title
attribute being evaluated?)
Here is a jsFiddle demonstrating the problem.
The problem is that by doing
scope: {
text: "@myDirective"
}
you are creating an isolated scope for the span element. Thus, when {{data.two}}
gets evaluated, there is no data
property in the scope. The '@myDirective'
allows that attribute to be evaluated and inserted into the isolated scope. That is why the '@' works for the title. One solution could be to not use an isolated scope for the directive, and then use the $observe
to set text
in the scope of the directive. See http://jsfiddle.net/sEMeA/9/