Angular directive attributes not evaluating
I've tried the answer mentioned here but no luck (I'm using angularjs 1.3). My problem has two parts
1) Complex attributes are not passed as objects, despite using '=' (see code below) in scope
2) the function that must evaluate to provide one-way binding is also passed as a string instead
sample selection,
<button type="button" class="btn btn-success" ng-click="RestEditCtrl.saveRestaurantDetails();">
<smart-btn-label btn-state="RestEditCtrl.ajaxState(RestEditCtrl.restaurant.id)"
when-normal="{label: 'Save', icon: 'glyphicon-floppy-disk' }"
when-active="{label: 'Saving...', icon: 'glyphicon-refresh glyphicon-spin-animate'}"
when-success="{label: 'Saved!', icon: 'glyphicon glyphicon-floppy-saved'}"
when-error="{label: 'Try saving again', icon: 'glyphicon glyphicon-exclamation-sign'}"></smart-btn-label>
</button>
directive code,
angular.module("app")
.directive('smartBtnLabel', function () {
return {
restrict: 'E',
scope: {
btnState: '&', // not working, @ evaluates but that defeats my purpose
whenActive: '=', // not evaluating any which way, it always comes as string
whenError: '=',
whenSuccess: '=',
whenNormal: '='
},
link: function (scope, elem, attrs) {
console.log(attrs);
var curState = "normal",
curLabel = attrs.whenNormal ? attrs.whenNormal.label : "",
curIcon = attrs.whenNormal ? attrs.whenNormal.icon : "";
if (attrs.btnState) curState = attrs.btnState;
if(curState == "active"){
curLabel = attrs.whenActive ? attrs.whenActive.label : "";
curIcon = attrs.whenActive ? attrs.whenActive.icon : ""
} else if(curState == "success"){
curLabel = attrs.whenSuccess ? attrs.whenSuccess.label : "";
curIcon = attrs.whenSuccess ? attrs.whenSuccess.icon : ""
} else if(curState == "error"){
curLabel = attrs.whenError ? attrs.whenError.label : "";
curIcon = attrs.whenError ? attrs.whenError.icon : ""
}
scope.curLabel = curLabel;
scope.curIcon = curIcon;
},
template: '<span aria-hidden="true" ng-show="curIcon" class="glyphicon {{curIcon}}" ></span>' +
'<span ng-show="curLabel"> {{curLabel}}</span>'
};
});
What am I doing wrong here?: --(
Decision
Thanks to PSL, this is what I got:
angular.module("app")
.directive('smartBtnLabel', function () {
return {
restrict: 'E',
scope: {
btnState: '&',
whenActive: '&',
whenError: '&',
whenSuccess: '&',
whenNormal: '&'
},
controller: ['$scope', function($scope){
var vm = this;
vm.props = {icon: "", label: ""};
var _setProperties = function () {
var _btnState = "normal";
if ($scope.btnState) _btnState = $scope.btnState();
if (_btnState == "active" && $scope.whenActive) vm.props = $scope.whenActive();
else if (_btnState == "success" && $scope.whenSuccess) vm.props = $scope.whenSuccess();
else if (_btnState == "error" && $scope.whenError) vm.props = $scope.whenError();
else if ($scope.whenNormal) vm.props = $scope.whenNormal();
};
if($scope.btnState){
$scope.$watch($scope.btnState, function () {
_setProperties();
});
}
_setProperties();
}],
controllerAs : "smartBtnLabelCtrl",
template: '<span aria-hidden="true" ng-show="smartBtnLabelCtrl.props.icon" class="glyphicon {{smartBtnLabelCtrl.props.icon}}" ></span>' +
'<span ng-show="smartBtnLabelCtrl.props.label"> {{smartBtnLabelCtrl.props.label}}</span>'
};
});
source to share
1) Complex attributes are not passed as objects, despite using '=' (see code below) in scope
This is because you get them as attrs.whenNormal
, which is a string (JSON). Instead, you just need to access it from the scope, i.e. scope.whenNormal
... It will be the same as scope.$eval(attrs.whenNormal)
or JSON.parse(attrs.whenNormal)//provided your JSON is valid
. But two-way binding doesn't make much sense here.
2) the function that needs to evaluate to provide one-way binding is also passed as a string.
This is because when you use function bindings, they are evaluated as a getter with the bound values (you specified the bound value as RestEditCtrl.restaurant.id
). Inorder to access the value, if the function ajaxState
returns something you need to do curState = scope.btnState();
instead curState = attrs.btnState
, basically evaluate the getter to get the value.
source to share