AngularJS - How to use ng-if without an HTML element

Is there a way to tell AngularJS not to display the top HTML element that has the ng-if directive. I want angular to display only content for children.

Angular Code:

<div ng-if="checked" id="div1"> <div id="div2">ABC</div> <div id="div3">KLM</div> <div id="div4">PQR</div> </div> 

Highlighted HTML:

  <div id="div1"> <div id="div2">ABC</div> <div id="div3">KLM</div> <div id="div4">PQR</div> </div> 

What I want:

  <div id="div2">ABC</div> <div id="div3">KLM</div> <div id="div4">PQR</div> 

Here is the fiddle. http://jsfiddle.net/9mgTS/ . I do not want #div1 in HTML. I just want #div2,3,4 if checked is true .

A possible solution might add ng-if to all the children, but I don't want to do this.

+48
javascript angularjs
Nov 01 '13 at 5:38
source share
6 answers

There is an undocumented pair of ng-if-start and ng-if-end directives here that you can use to do this. They behave similarly to the documented ng-repeat-start and ng-repeat-end directives, and you can view the tags for them if you want.

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 will be shown, and the last four li will be hidden.

Here is a live example in CodePen: http://codepen.io/anon/pen/PqEJYV

There are also ng-show-start and ng-show-end directives that work exactly as you would expect from them.

+44
Jun 28 '15 at 14:44
source share

If you are happy to create a custom directive, you can programmatically apply ng-if to children and smooth out 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> 

Highlighted 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/

+6
Feb 24 '15 at 12:44
source share

I do not understand why you do not want to use the parent div, but that would be a good solution if you have +20 divs:

HTML

  <div ng-repeat="div in divs" ng-if="checked" id="{{div.name}}">{{div.content}}</div> 

Js

 app.controller('myCtrl', function($scope) { $scope.checked = true; $scope.divs = { {'name': 'div2', content:'ABC'}, {'name': 'div3', content:'KLM'}, {'name': 'div4', content:'PQR'} } }); 
0
Jun 16 '14 at 8:30
source share

Here's Angular 1.21 solution:

HTML:

 <div ng-app="app" ng-controller="ctrl"> <div ng-iff="checked" id="div1"> <div id="div2">ABC</div> <div id="div3">KLM</div> <div id="div4">PQR</div> </div> <button ng-click="toggleCheck()">Toggle Check</button> </div> 

JAVASCRIPT:

 angular.module('app', []). controller('ctrl', function ($scope) { $scope.checked = true; $scope.toggleCheck = function () { $scope.checked = !$scope.checked; }; }). directive('ngIff', function ($compile) { return { compile: function compile(tElement, tAttrs, transclude) { return { pre: function preLink(scope, iElement, iAttrs, controller) { var bindingElem = iElement.attr('ng-iff'); var children = iElement.children(); angular.forEach(children,function(c){ angular.element(c).attr('ng-if',bindingElem); }); $compile(children)(scope, function(newElem){ iElement.replaceWith(newElem); }); } }; } }; }); 

JSFIDDLE .

0
Jun 12 '15 at 4:45
source share

Try the following: - http://jsfiddle.net/adiioo7/9mgTS/1/

div1 is the parent container for div2,div3,div4 unless you want div1 in the output html to use this: -

 <div ng-app="App">Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /> <br/>Show when checked: <div class="div2" ng-if="checked">ABC</div> <div class="div3" ng-if="checked">KLM</div> <div class="div4" ng-if="checked">PQR</div> </div> 

EDIT: -

Using angular js and jQuery: - http://jsfiddle.net/adiioo7/9mgTS/3/

Assign a generic class ( myClass example) to all elements that belong to this group.

JS: -

 angular.module('App', []); function myController($scope) { $scope.change = function () { angular.element(".myClass").toggle(); }; } 

HTML: -

 <div ng-app="App" ng-Controller="myController">Click me: <input type="checkbox" ng-change="change()" ng-model="checked" ng-init="checked=true" /> <br/>Show when checked: <div id="div2" class="myClass">ABC</div> <div id="div3" class="myClass">KLM</div> <div id="div4" class="myClass">PQR</div> </div> 
-2
Nov 01 '13 at 5:48 on
source share

This seems to be an old question, but I got a similar requirement

 <div ng-if="checked" id="div1"> <div id="div2">ABC</div> <div id="div3">KLM</div> <div id="div4">PQR</div> </div> 

I did it

 <mytag ng-if="checked" id="div1"> <div id="div2">ABC</div> <div id="div3">KLM</div> <div id="div4">PQR</div> </mytag> 

where mytag is just any name that is not an html element, if it does not interfere with the layout, this works for me

-2
Jun 12 '15 at 4:13
source share



All Articles