Reputation: 11131
I have a directive defined like this:
myApp.directive('stoplight', function() {
return {
restrict:'E',
transclude: true,
scope: {
value: '@'
},
link: function(scope, element) {
if (scope.value === true) {
element.html('<i class="icon icon-true green"></i>');
} else if (scope.value === false) {
element.html('<i class="icon icon-false red"></i>');
} else {
element.html('<i class="icon icon-unknown yellow"></i>');
}
}
};
});
When I use this directive, I use the following markup:
<stoplight value="boolValue" />
My controller behind stoplight looks like this:
myApp.controller('MyController', function($scope, $http) {
$scope.boolValue = null;
$scope.init = function() {
$scope.boolValue = false;
$http.jsonp('http://anyorigin.com/get?url=www.google.com&callback=JSON_CALLBACK')
.success(function() {
console.log('woohoo!');
$scope.boolValue = true;
});
};
$scope.init();
}};
I have two issues, and neither make sense to me.
@
' in my directive doesn't work. If I change the '@
' to a '=
', the link function works somewhat as expected. However, I want to use one-way binding instead of two-binding for performance reasons.$scope.boolValue = true;
in my success callback doesn't update the UI. The icon stays red. I can set the value to null, expecting yellow, but it stays red. If I look in the console window though, I can see 'woohoo!
'. I don't understand why updating boolValue
outside of the callback works, yet in the callback, it just doesn't work. I do not see any error in the console window or anything of that nature.Can someone please help me identify why this isn't working? I'm not sure if this is one issue or two issues. I think they both have to do with the binding. However, I'm not sure how to remedy this.
Thank you.
Upvotes: 1
Views: 1281
Reputation: 11
Regarding issue #1, I believe it is occurring because '@' always results in a string value. So you probably need scope.value === 'true' and scope.value === 'false'.
Regarding issue #2, as neilhem already answered, you need the double curly braces:
<stoplight value="{{boolValue}}" />
Upvotes: 1
Reputation: 1246
For #1: using @ doesn't mean 'one-way binding', it means to take evaluated value of the DOM attribute, not the variable, so scope.value
will result in a string value of 'boolValue', you could use <stoplight value="{{ boolValue }}" />
in your template or =
in your directive. Here is a great explanation how @
and =
differs.
For #2: Your UI doesn't update, because you directive is not watching for changes on attribute value. When directive is initialized, it takes first value and does the stuff in your directive, however - that's it. When value changes, nothing should happen in directive. Try this:
myApp.directive('stoplight', function() {
return {
restrict:'E',
transclude: true,
scope: {
value: '@'
},
link: function(scope, element) {
scope.$watch(function() { return scope.value; }, function(value) {
if (value === true) {
element.html('<i class="icon icon-true green"></i>');
} else if (value === false) {
element.html('<i class="icon icon-false red"></i>');
} else {
element.html('<i class="icon icon-unknown yellow"></i>');
}
});
}
};
});
Upvotes: 0