*ngIf and *ngFor on same element causing error

后端 未结 16 2068
自闭症患者
自闭症患者 2020-11-22 02:37

I\'m having a problem with trying to use Angular\'s *ngFor and *ngIf on the same element.

When trying to loop through the collection in th

相关标签:
16条回答
  • 2020-11-22 03:01

    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>
    
    0 讨论(0)
  • 2020-11-22 03:02

    You can't have ngFor and ngIf on the same element. What you could do is hold off on populating the array you're using in ngFor until the toggle in your example is clicked.

    Here's a basic (not great) way you could do it: http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P

    0 讨论(0)
  • 2020-11-22 03:06

    I didn't want to wrap my *ngFor into another div with *ngIf or use [ngClass], so I created a pipe named show:

    show.pipe.ts

    export class ShowPipe implements PipeTransform {    
      transform(values: any[], show: boolean): any[] {
        if (!show) {
          return[];
        }
        return values;
      }
    }
    

    any.page.html

    <table>
      <tr *ngFor="let arr of anyArray | show : ngIfCondition">
        <td>{{arr.label}}</td>
      </tr>
    </table>
    
    0 讨论(0)
  • 2020-11-22 03:07

    You can not use more than one Structural Directive in Angular on the same element, it makes a bad confusion and structure, so you need to apply them in 2 separate nested elements(or you can use ng-container), read this statement from Angular team:

    One structural directive per host element

    Someday you'll want to repeat a block of HTML but only when a particular condition is true. You'll try to put both an *ngFor and an *ngIf on the same host element. Angular won't let you. You may apply only one structural directive to an element.

    The reason is simplicity. Structural directives can do complex things with the host element and its descendents. When two directives lay claim to the same host element, which one takes precedence? Which should go first, the NgIf or the NgFor? Can the NgIf cancel the effect of the NgFor? If so (and it seems like it should be so), how should Angular generalize the ability to cancel for other structural directives?

    There are no easy answers to these questions. Prohibiting multiple structural directives makes them moot. There's an easy solution for this use case: put the *ngIf on a container element that wraps the *ngFor element. One or both elements can be an ng-container so you don't have to introduce extra levels of HTML.

    So you can use ng-container (Angular4) as the wrapper (will be deleted from the dom) or a div or span if you have class or some other attributes as below:

    <div class="right" *ngIf="show">
      <div *ngFor="let thing of stuff">
        {{log(thing)}}
        <span>{{thing.name}}</span>
      </div>
    </div>
    
    0 讨论(0)
  • 2020-11-22 03:07

    Table below only lists items that have a "beginner" value set. Requires both the *ngFor and the *ngIf to prevent unwanted rows in html.

    Originally had *ngIf and *ngFor on the same <tr> tag, but doesn't work. Added a <div> for the *ngFor loop and placed *ngIf in the <tr> tag, works as expected.

    <table class="table lessons-list card card-strong ">
      <tbody>
      <div *ngFor="let lesson of lessons" >
       <tr *ngIf="lesson.isBeginner">
        <!-- next line doesn't work -->
        <!-- <tr *ngFor="let lesson of lessons" *ngIf="lesson.isBeginner"> -->
        <td class="lesson-title">{{lesson.description}}</td>
        <td class="duration">
          <i class="fa fa-clock-o"></i>
          <span>{{lesson.duration}}</span>
        </td>
       </tr>
      </div>
      </tbody>
    
    </table>
    
    0 讨论(0)
  • 2020-11-22 03:09

    Updated to angular2 beta 8

    Now as from angular2 beta 8 we can use *ngIf and *ngFor on same component see here.

    Alternate:

    Sometimes we can't use HTML tags inside another like in tr, th (table) or in li (ul). We cannot use another HTML tag but we have to perform some action in same situation so we can HTML5 feature tag <template> in this way.

    ngFor using template:

    <template ngFor #abc [ngForOf]="someArray">
        code here....
    </template>
    

    ngIf using template:

    <template [ngIf]="show">
        code here....
    </template>    
    

    For more information about structural directives in angular2 see here.

    0 讨论(0)
提交回复
热议问题