145

Can I use ngIf without an extra container element?

<tr *ngFor="...">
  <div *ngIf="...">
    ...
  </div>
  <div *ngIf="!...">
    ...
  </div>
</tr>

It doesn't work in a table because that would make invalid HTML.

janispritzkau
  • 1,877
  • 2
  • 12
  • 15

5 Answers5

243

ng-container is preferred over template:

<ng-container *ngIf="expression">

See:

Angular 2 ng-container

https://github.com/angular/angular.io/issues/2303

Community
  • 1
  • 1
Alexander Taylor
  • 16,574
  • 14
  • 62
  • 83
21

I found a method for that on: https://angular.io/docs/ts/latest/guide/template-syntax.html#!#star-template.

You can simply use the <template> tag and replace *ngIf with [ngIf] like this.

<template [ngIf]="...">
  ...
</template>
janispritzkau
  • 1,877
  • 2
  • 12
  • 15
  • good but *ngIf itslef creates an `template` tag ,by default angular directives prefix with * creates an template tag. so both are same `[ngIf] and *ngIf` – Pardeep Jain Apr 03 '16 at 08:01
  • 1
    With `*ngIf` you have an element inside the template, you do not if you write the `template` yourself. Under certain circumstances the extra element could interfere. – Max Apr 14 '16 at 09:39
  • Can we put `template` tag inside, `tr`/`td` tag? – Pankaj Parkar Aug 09 '16 at 05:57
  • Yes it's kind of a special element. Per definition it's not allowed https://www.w3.org/TR/html401/struct/tables.html#h-11.2.3 but it will work and render. If Iam using *ngIf it isn't working btw. but with [ngIf] it does. May I ask if you can tell me why that is? – sascha10000 Oct 06 '16 at 13:49
  • 1
    @sascha10000 Because having `*ngIf="foo"` is equivalent to the wrapping ` – Franklin Yu Dec 12 '16 at 06:38
4

You can't put div directly inside tr, that would make invalid HTML. tr can only have td/th/table element in it & inside them you could have other HTML elements.

You could slightly change your HTML to have *ngFor over tbody & have ngIf over tr itself like below.

<tbody *ngFor="...">
  <tr *ngIf="...">
    ...
  </tr>
  <tr  *ngIf="!...">
    ...
  </tr>
  ..
</tbody>
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • It would basically solve the problem but you'll trade off the core ability you get with tbody. If you have a big table you can fix the head an just scroll the tbody. Your tbody would have the role of tr and tr would have the role of an additional wrapper. If there's no need for scrolling and fixing the head at top this is a pragmatic solution. My reference for what I said: https://www.w3.org/TR/html401/struct/tables.html#h-11.2.3 – sascha10000 Oct 06 '16 at 13:06
1

You can try this:

<ng-container *ngFor="let item of items;">
    <tr *ngIf="item.active">
        <td>{{item.name}}</td>
    </tr>
 </ng-container>
 

Here, I have iterate loop in ng container so it will not create extra dom and later in tr tag check condition if I want to render or not.

Jitendra
  • 286
  • 1
  • 2
  • 7
0

adding brackets resolves this issue

 <ng-container *ngIf="(!variable| async)"></ng-container>
Sourabh Shah
  • 140
  • 2
  • 11