String Interpolation Won't Work when Setting Attribute Values on a Custom Directive
angularjs
Solution
A few things:
- directive attributes in HTML need to use kebab-case
- you don't need an isolate scope (in fact it is causing problems); instead use `scope: true`
- you need to set local scope properties so your template can pick them up
- `$observe` must be used to get the value of interpolated attributes (i.e., attributes that use {{}}s)
HTML:
<rating current-rating-value="{{ratable.currentvalue}}" max-rating-value="10"></rating>
Directive:
link: function (scope, element, attributes) {
attributes.$observe('currentRatingValue', function(newValue) {
console.log('newValue=',newValue);
scope.currentRatingValue = newValue
})
scope.maxRatingValue = attributes.maxRatingValue;
console.log('mrv=',attributes.maxRatingValue);
}
Fiddle
Here is a version that uses an isolate scope:
.directive("rating", function () {
return {
restrict: "E",
scope: { currentRatingValue: '@',
maxRatingValue: '@' },
template: "<div class='rating'>Current rating: {{currentRatingValue}}"
+ " out of {{maxRatingValue}}</div>",
};
});
Fiddle
If you want to see the value of an isolate scope property in your link function, you'll need to use `$observe` or `$watch` because we used '@'. If you use '=' (for two-way databinding), you don't need to use `$observe` or `$watch`.
Problem
Should I be able to pass attributes from the $scope into a custom directive like this? ``` <div ng-repeat="ratable in ratables"> <div>How much do you like {{ratable.name}}?</div> <!-- CONFUSED - First element does not work, second element does --> <rating currentRatingValue="{{ratable.currentvalue}}" maxRatingValue="10"></rating> </div> ``` The hardwired "10" passes through into the directive just fine, but the string interpolation when I try to pass {{ratable.currentvalue}} never seems to occur. Am I doing something obviously wrong? http://jsfiddle.net/ADukg/2168/ ``` var myApp = angular.module('myApp',[]) .directive("rating", function () { return { restrict: "E", scope: {}, template: "<div class='rating'>Current rating: {{currentratingvalue}} out of {{maxratingvalue}}</div>", link: function (scope, element, attributes) { console.log(attributes.currentratingvalue); // Does not work but seems like it should console.log(attributes.maxratingvalue); // Does work } }; }); function MyCtrl($scope) { $scope.name = 'Superhero'; $scope.ratables = [ { name: "sledding", currentvalue: 3, maxvalue: 5 }, { name: "water skiing", currentvalue: 7, maxvalue: 10 }, { name: "whitewater rafting", currentvalue: null, maxvalue: 10 } ]; } <div> <div ng-controller="MyCtrl"> Hello, {{name}}! <div ng-repeat="ratable in ratables"> <div>How much do you like {{ratable.name}}?</div> <!-- CONFUSED - First element does not work, second element does --> <rating currentRatingValue="{{ratable.currentvalue}}" maxRatingValue="10"></rating> </div> </div> </div> ```