<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js@1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng-app="myModule">
<div directive-if="{'logger': 'myValue == 1'}"
logger="testValue">
<p>"logger" directive exists? <strong>{{logger}}</strong></p>
</div>
</div>
</body>
</html>
angular.module('myModule', [])
// Set some defaults on the $rootScope.
.run(function($rootScope) {
$rootScope.myValue = 1;
$rootScope.logger = false;
})
// A test directive that can be added/removed
// by the "directiveIf" directive.
.directive('logger', [
function() {
return {
compile: function() {
return {
pre: function() {
console.log('logger.pre');
},
post: function(scope, element, attr) {
console.log('logger: value=', attr.logger);
scope.logger = true;
}
};
}
};
}
])
/**
* The "directiveIf" directive allows other directives
* to be dynamically removed from this element.
*
* Any number of directives can be controlled with the object
* passed in the "directive-if" attribute on this element:
*
* {'attributeName': 'expression'[, 'attribute': 'expression']}
*
* If `expression` evaluates to `false` then `attributeName`
* will be removed from this element.
*
* Usage:
*
* <any directive-if="{'myDirective': 'expression'}"
* my-directive>
* </any>
*
*/
.directive('directiveIf', ['$compile',
function($compile) {
// Error handling.
var compileGuard = 0;
// End of error handling.
return {
// Set a high priority so we run before other directives.
priority: 100,
// Set terminal to true to stop other directives from running.
terminal: true,
compile: function() {
return {
pre: function(scope, element, attr) {
// Error handling.
//
// Make sure we don't go into an infinite compile loop
// if something goes wrong.
compileGuard++;
if (compileGuard >= 10) {
console.log('directiveIf: infinite compile loop!');
return;
}
// End of error handling.
// Get the set of directives to apply.
var directives = scope.$eval(attr.directiveIf);
angular.forEach(directives, function(expr, directive) {
// Evaluate each directive expression and remove
// the directive attribute if the expression evaluates
// to `false`.
var result = scope.$eval(expr);
if (result === false) {
// Set the attribute to `null` to remove the attribute.
//
// See: https://docs.angularjs.org/api/ng/type/$compile.directive.Attributes#$set
attr.$set('logger', null)
}
});
// Remove our own directive before compiling
// to avoid infinite compile loops.
attr.$set('directiveIf', null);
// Recompile the element so the remaining directives
// can be invoked.
var result = $compile(element)(scope);
// Error handling.
//
// Reset the compileGuard after compilation
// (otherwise we can't use this directive multiple times).
//
// It should be safe to reset here because we will
// only reach this code *after* the `$compile()`
// call above has returned.
compileGuard = 0;
}
};
}
};
}
]);
/* Styles go here */