Reputation: 7141
I am trying to create a directive that can show or hide the element it is on dependent on whether a user has a visibility of a feature:
I would like to apply this directive like below:
<div feature="some-feature-name">
I have the power!
</div>
angular
.module('app', [])
.directive('feature', ['userService' function(){
return {
restrict:'A',
scope: {},
link: function(scope, elem, attrs, ngModel){
// Logic to work out whether someone is permitted to see that feature
if(userService.canSeeFeature(featureName){
}
// Hides the the element it is on if not.
}
};
}]);
Is this possible?
Upvotes: 1
Views: 62
Reputation: 16609
There are two main steps to doing this - getting hold of the feature to check from the attribute and doing the show/hide of the element.
The first thing to note is how to get hold of the feature from the attribute
<div feature="y">AccessGranted</div>
You do this in the using the attrs
parameter already in the link method. Simply
link: function(scope, elem, attrs){
var theFeature = attrs['feature'];
var hasAccess = userService.canSeeFeature(theFeature);
}
Next you need to hide the element if they do not have access. There are a couple of options for doing this.
The "pure Angular" way to do this is to set a variable on your scope
saying whether the user has access or not, then use ng-show
to only show it if the variable is true:
link: function(scope, elem, attrs){
scope.hasAccess = userService.canSeeFeature(attrs['feature']);
}
<div feature="y" ng-show="hasAccess">Access Granted</div>
However the point of the directive is to do this for you. In this case, I think it is reasonable to use some simple jQuery (more specifically jqLite) to do this in the directive code. If you have full jQuery in your page elem.hide()
is nicer, but jqLite doesn't support this, so you will need to use css()
:
link: function(scope, elem, attrs){
// check for access
if(!userService.canSeeFeature(attrs['feature'])) {
// hide the element
elem.css('display', 'none');
}
}
Here is a working sample based on your plunkr:
angular
.module('app', [])
.service('userService', function() {
return {
canSeeFeature: function(feature) {
// test - only allow access to y
return feature === 'y';
}
}
})
.directive('feature', ['userService', function(userService) {
return {
restrict:'A',
scope: {},
link: function(scope, elem, attrs, ngModel){
// check for access
if(!userService.canSeeFeature(attrs['feature'])) {
// access denied - hide the element
elem.css('display', 'none');
}
}
};
}]);
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>AngularJS Formatters and Parse</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.js"></script>
</head>
<body ng-app="app">
<div feature="y">y - I have the power!</div>
<div feature="n">n - I don't have the power :(</div>
<div feature="y">y - I also have the power!</div>
</body>
</html>
Upvotes: 1
Reputation: 13138
A modified version of ngShow directive :
var featureDirective = ['$animate', 'userService', function($animate, userService) {
return {
restrict: 'A',
multiElement: true,
link: function(scope, element, attr) {
scope.$watch(attr.feature, function featureWatchAction(value) {
$animate[userService.isAllowed(value) ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {
tempClasses: NG_HIDE_IN_PROGRESS_CLASS
});
});
}
};
}];
Upvotes: 1