148

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.

5 Answers 5

249

ng-container is preferred over template:

<ng-container *ngIf="expression">

See:

Angular 2 ng-container

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

Sign up to request clarification or add additional context in comments.

3 Comments

You should add a sample "generate" HTML snippet, to make it clear that an HTML <ng-container> element doesn't get created.
I come here twice a day. I can't get to stick that in my head.
ng-container seems to generate a div in our case?
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>

5 Comments

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
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.
Can we put template tag inside, tr/td tag?
Yes it's kind of a special element. Per definition it's not allowed 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 Because having *ngIf="foo" is equivalent to the wrapping <template [ngIf]="foo"> tag. In short, template + [] == *, so [] != *. * makes sense in any element except template.
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>

1 Comment

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: w3.org/TR/html401/struct/tables.html#h-11.2.3
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.

Comments

0

adding brackets resolves this issue

 <ng-container *ngIf="(!variable| async)"></ng-container>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.