AngularJS - How to use ng-if without HTML element
There's a currently-undocumented pair of directives, ng-if-start
and ng-if-end
, that you can use for this. They behave analogously to the documented ng-repeat-start
and ng-repeat-end
directives, and you can see the unit tests for them if you like.
For example, given the following code:
<ul>
<li ng-if-start="true">a</li>
<li>b</li>
<li>c</li>
<li ng-if-end>d</li>
<li ng-if-start="false">1</li>
<li>2</li>
<li>3</li>
<li ng-if-end>4</li>
</ul>
the first four li
s will be shown and the final four li
s will be hidden.
Here's a live example on CodePen: http://codepen.io/anon/pen/PqEJYV
There are also ng-show-start
and ng-show-end
directives that work exactly the way you would expect them to.
If you are happy to create a custom directive, you can apply the ng-if to the children programmatically and flatten the DOM in the process:
Directive Code:
.directive('ngBatchIf', function() {
return {
scope: {},
compile: function (elm, attrs) {
// After flattening, Angular will still have the first element
// bound to the old scope, so we create a temporary marker
// to store it
elm.prepend('<div style="display: none"></div>');
// Flatten (unwrap) the parent
var children = elm.children();
elm.replaceWith(children);
// Add the ng-if to the children
children.attr('ng-if', attrs.ngBatchIf);
return {
post: function postLink(scope, elm) {
// Now remove the temporary marker
elm.remove();
}
}
}
}
})
Angular Code:
<div id="div1" ng-batch-if="checked">
<div id="div2">ABC</div>
<div id="div3">KLM</div>
<div id="div4">PQR</div>
</div>
Rendered HTML:
<div id="div2" ng-if="checked">ABC</div>
<div id="div3" ng-if="checked">KLM</div>
<div id="div4" ng-if="checked">PQR</div>
Fiddle: http://jsfiddle.net/o166xg0s/4/