*ngIf and *ngFor on same element causing error *ngIf and *ngFor on same element causing error angular angular

*ngIf and *ngFor on same element causing error


Angular v2 doesn't support more than one structural directive on the same element.
As a workaround use the <ng-container> element that allows you to use separate elements for each structural directive, but it is not stamped to the DOM.

<ng-container *ngIf="show">  <div *ngFor="let thing of stuff">    {{log(thing)}}    <span>{{thing.name}}</span>  </div></ng-container>

<ng-template> (<template> before Angular v4) allows to do the same but with a different syntax which is confusing and no longer recommended

<ng-template [ngIf]="show">  <div *ngFor="let thing of stuff">    {{log(thing)}}    <span>{{thing.name}}</span>  </div></ng-template>


As everyone pointed out even though having multiple template directives in a single element works in angular 1.x it is not allowed in Angular 2. you can find more info from here : https://github.com/angular/angular/issues/7315

2016 angular 2 beta

solution is to use the <template> as a placeholder, so the code goes like this

<template *ngFor="let nav_link of defaultLinks"  >   <li *ngIf="nav_link.visible">       .....   </li></template>

but for some reason above does not work in 2.0.0-rc.4 in that case you can use this

<template ngFor let-nav_link [ngForOf]="defaultLinks" >   <li *ngIf="nav_link.visible">       .....   </li> </template>

Updated Answer 2018

With updates, right now in 2018 angular v6 recommend to use <ng-container> instead of <template>

so here is the updated answer.

<ng-container *ngFor="let nav_link of defaultLinks" >   <li *ngIf="nav_link.visible">       .....   </li> </ng-container>


As @Zyzle mentioned, and @Günter mentioned in a comment (https://github.com/angular/angular/issues/7315), this is not supported.

With

<ul *ngIf="show">  <li *ngFor="let thing of stuff">    {{log(thing)}}    <span>{{thing.name}}</span>  </li></ul>

there are no empty <li> elements when the list is empty. Even the <ul> element does not exist (as expected).

When the list is populated, there are no redundant container elements.

The github discussion (4792) that @Zyzle mentioned in his comment also presents another solution using <template> (below I'm using your original markup ‐ using <div>s):

<template [ngIf]="show">  <div *ngFor="let thing of stuff">    {{log(thing)}}    <span>{{thing.name}}</span>  </div></template>

This solution also does not introduce any extra/redundant container elements.