Foo*_*bar 49 javascript angularjs angularjs-directive
我想创建一个指令,根据来自服务的值(例如,检查用户角色)检查dom中是否应该存在元素.
相应的指令如下所示:
angular.module('app', []).directive('addCondition', function($rootScope) {
return {
restrict: 'A',
compile: function (element, attr) {
var ngIf = attr.ngIf,
value = $rootScope.$eval(attr.addCondition);
/**
* Make sure to combine with existing ngIf!
* I want to modify the expression to be evalued by ngIf here based on a role
* check for example
*/
if (ngIf) {
value += ' && ' + ngIf;
}
attr.$set('ng-if', value);
}
};
});
Run Code Online (Sandbox Code Playgroud)
最后,元素附加了ng-if属性,但不知何故,它不适用于元素,它仍然存在于dom中.所以这显然是一种错误的做法.
这个小提琴显示了问题:http://jsfiddle.net/L37tZ/2/
谁能解释为什么会这样?有没有其他方式可以实现类似的行为?应考虑现有的ngIfs.
用法: <div rln-require-roles="['ADMIN', 'USER']">I'm hidden when theses role requirements are not satifisfied!</div>
.directive('rlnRequireRoles', function ($animate, Session) {
return {
transclude: 'element',
priority: 600,
terminal: true,
restrict: 'A',
link: function ($scope, $element, $attr, ctrl, $transclude) {
var block, childScope, roles;
$attr.$observe('rlnRequireRoles', function (value) {
roles = $scope.$eval(value);
if (Session.hasRoles(roles)) {
if (!childScope) {
childScope = $scope.$new();
$transclude(childScope, function (clone) {
block = {
startNode: clone[0],
endNode: clone[clone.length++] = document.createComment(' end rlnRequireRoles: ' + $attr.rlnRequireRoles + ' ')
};
$animate.enter(clone, $element.parent(), $element);
});
}
} else {
if (childScope) {
childScope.$destroy();
childScope = null;
}
if (block) {
$animate.leave(getBlockElements(block));
block = null;
}
}
});
}
};
});
Run Code Online (Sandbox Code Playgroud)
在指令中添加优先级非常重要,否则不会评估附加到该元素的其他指令!
Jos*_*cha 80
您可以ngIf
在自己的指令中重用,如下所示:
/** @const */ var NAME = 'yourCustomIf';
yourApp.directive(NAME, function(ngIfDirective) {
var ngIf = ngIfDirective[0];
return {
transclude: ngIf.transclude,
priority: ngIf.priority,
terminal: ngIf.terminal,
restrict: ngIf.restrict,
link: function($scope, $element, $attr) {
var value = $attr[NAME];
var yourCustomValue = $scope.$eval(value);
$attr.ngIf = function() {
return yourCustomValue;
};
ngIf.link.apply(ngIf, arguments);
}
};
});
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它
<div your-custom-if="true">This is shown</div>
Run Code Online (Sandbox Code Playgroud)
它将使用随附的所有"功能" ngIf
.
hil*_*ius 48
Joscha的答案相当不错,但实际上如果你使用ng-if,这将不起作用.我拿了Joscha的代码并添加了几行来将它与现有的ng-if指令结合起来:
angular.module('myModule').directive('ifAuthenticated', ['ngIfDirective', 'User', function(ngIfDirective, User) {
var ngIf = ngIfDirective[0];
return {
transclude: ngIf.transclude,
priority: ngIf.priority - 1,
terminal: ngIf.terminal,
restrict: ngIf.restrict,
link: function(scope, element, attributes) {
// find the initial ng-if attribute
var initialNgIf = attributes.ngIf, ifEvaluator;
// if it exists, evaluates ngIf && ifAuthenticated
if (initialNgIf) {
ifEvaluator = function () {
return scope.$eval(initialNgIf) && User.isAuthenticated();
}
} else { // if there's no ng-if, process normally
ifEvaluator = function () {
return User.isAuthenticated();
}
}
attributes.ngIf = ifEvaluator;
ngIf.link.apply(ngIf, arguments);
}
};
}]);
Run Code Online (Sandbox Code Playgroud)
那么如果可以做以下事情:
<input type="text" ng-model="test">
<div ng-if="test.length > 0" if-authenticated>Conditional div</div>
Run Code Online (Sandbox Code Playgroud)
div
只有在您通过身份验证并且&测试输入不为空时,条件才会显示.