Aynı öğede * ngIf ve * ng


473

Angular *ngForve *ngIfaynı öğeyi kullanmaya çalışırken sorun yaşıyorum .

İçindeki koleksiyonda döngü oluşturmaya çalıştığınızda *ngFor, koleksiyon, nullşablondaki özelliklerine erişmeye çalışılırken görünür ve sonuç olarak başarısız olur.

@Component({
  selector: 'shell',
  template: `
    <h3>Shell</h3><button (click)="toggle()">Toggle!</button>

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

export class ShellComponent implements OnInit {

  public stuff:any[] = [];
  public show:boolean = false;

  constructor() {}

  ngOnInit() {
    this.stuff = [
      { name: 'abc', id: 1 },
      { name: 'huo', id: 2 },
      { name: 'bar', id: 3 },
      { name: 'foo', id: 4 },
      { name: 'thing', id: 5 },
      { name: 'other', id: 6 },
    ]
  }

  toggle() {
    this.show = !this.show;
  }

  log(thing) {
    console.log(thing);
  }

}

Ben kolay bir çözüm *ngIfbir seviye yukarı taşımak olduğunu biliyorum ama bir liste öğeleri üzerinde döngü gibi senaryolar için ul, ben likoleksiyon boşsa, boş veya benim lis yedek konteyner elemanları sarılmış.

Bu plnkr'de örnek .

Konsol hatasını not edin:

EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]

Yanlış bir şey mi yapıyorum yoksa bu bir hata mı?



Yanıtlar:


680

Açısal v2, aynı öğe üzerinde birden fazla yapısal yönergeyi desteklemez.
Geçici bir çözüm olarak <ng-container>, her yapısal yönerge için ayrı öğeler kullanmanıza izin veren öğeyi kullanın, ancak DOM'ye damgalanmamıştır .

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

<ng-template>( <template>Açısal v4'ten önce) aynı şeyi yapmanıza izin verir, ancak kafa karıştırıcı olan ve artık önerilmeyen farklı bir sözdizimi ile

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

5
Çok teşekkürler. Şaşırtıcı bir şekilde hala belgesiz: github.com/angular/angular.io/issues/2303
Alex Fuentes

7
İçinde * ngFor'umuz olduğunda kod nasıl görünecek? IE IF koşulu, bir döngü öğesinin değerini temel alacaktır.
Yuvraj Patil

22
Sadece koymak ngForen <ng-container>eleman ve ngIfen <div>. Ayrıca iki iç içe <ng-container>sarılmış olabilir <div>. <ng-container>yalnızca DOM'a eklenmeyecek bir yardımcı öğedir.
Günter Zöchbauer

3
Kullanmanızı öneririm <ng-container>. Aynı şekilde davranır <template>ancak yapısal yönergeler için "normal" sözdiziminin kullanılmasına izin verir.
Günter Zöchbauer

2
Dokümantasyon şöyle diyor : "Ana bilgisayar öğesi başına bir yapısal yönerge": "Bu kullanım örneği için kolay bir çözüm var: * ngIf * * ngFor öğesini saran bir kap öğesinin üzerine koyun." - sadece yineleme
heringer

71

Tek bir öğede birden çok şablon yönergesine sahip olmasına rağmen herkesin işaret ettiği gibi Açısal 2'de izin verilmez. Buradan daha fazla bilgi bulabilirsiniz: https://github.com/angular/angular/issues/ 7315

2016 açısal 2 beta

çözüm <template>bir yer tutucu olarak kullanmaktır , böylece kod böyle gider

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

ancak yukarıdaki bazı nedenlerden dolayı 2.0.0-rc.4bu durumda çalışmaz.

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

Güncellenmiş Yanıt 2018

Güncellemeler ile, şimdi 2018'de açısal v6 <ng-container>yerine<template>

İşte güncellenmiş cevap.

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

29

@Zyzle'ın ve @ Günter'in bir yorumda belirtildiği gibi ( https://github.com/angular/angular/issues/7315 ), bu desteklenmez.

İle

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

<li>liste boş olduğunda boş öğe yoktur . <ul>Öğe bile mevcut değil (beklendiği gibi).

Liste doldurulduğunda, artık kap öğesi yoktur.

Github tartışması (4792) @Zyzle yaptığı açıklamada bahsettiği de kullanarak başka bir çözüm sunar <template>- (kullanarak ben orijinal işaretlemeyi kullanıyorum aşağıda <div>: ler)

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

Bu çözüm ayrıca herhangi bir ekstra / yedekli konteyner elemanı içermez.


1
Bunun neden kabul edilen cevap olmadığından emin değilim. <template>çıktıda görünmeyecek bir üst öğe eklemenin yoludur.
Evan Plaice

8

html biçiminde:

<div [ngClass]="{'disabled-field': !show}" *ngFor="let thing of stuff">
    {{thing.name}}
</div>

css olarak:

.disabled-field {
    pointer-events: none;
    display: none;
}

5

Sen olamaz ngForve ngIfaynı eleman üzerinde. Yapabileceğiniz şey ngFor, örneğinizdeki geçiş tıklanıncaya kadar kullandığınız diziyi doldurmaya devam etmektir.

İşte bunu yapmanın temel (harika değil) yolu: http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P


Neden ikisine birden sahip olamıyor? Ayrıntılı lütfen
maurycy

1
Burada bir tartışma var github.com/angular/angular/issues/4792
Zyzle

1
Bunun neden olduğunu biliyorum, sadece cevabın kalitesini artırmak, açıkçası you can'tgerçekten iyi bir cevap değil, kabul etmeyecek misin?
Maurycy

Tabii, birlikte kullanılmamalıdır çünkü şablon için belirli bir sıraya koymak, aynı sırayla yürütüleceklerini garanti etmez. Ancak bu, 'null özelliği' okunamıyor 'null' atıldığında tam olarak ne olduğunu açıklamaz.
Estus Flask

Hem * ngFor hem de * ngIf (yıldız işaretli) yapısal direktiflerdir ve <template> etiketi oluştururlar. NgIf gibi yapısal yönergeler sihirlerini HTML 5 şablon etiketini kullanarak yaparlar.
Pardeep Jain

5

Structural DirectiveAçısal'da aynı öğede birden fazla kullanamazsınız , kötü bir karışıklık ve yapı oluşturur, bu nedenle bunları 2 ayrı iç içe öğeye (veya kullanabilirsiniz ng-container) uygulamanız gerekir, bu ifadeyi Açısal ekipten okuyun:

Ana bilgisayar öğesi başına bir yapısal yönerge

Bir gün bir HTML bloğunu ancak belirli bir koşul doğru olduğunda tekrarlamak isteyeceksiniz. Bir ikisi koymak çalışacağım * ngFor ve * ngIf aynı ana unsuru üzerinde. Açısal izin vermez. Bir öğeye yalnızca bir yapısal yönerge uygulayabilirsiniz.

Nedeni basitlik. Yapısal direktifler ev sahibi eleman ve onun alt öğeleri ile karmaşık şeyler yapabilir. İki direktif aynı ana bilgisayar öğesini talep ettiğinde hangisi önceliklidir? Hangisi önce gitmeli, NgIf veya NgFor? NgIf, NgFor'un etkisini iptal edebilir mi? Öyleyse (ve öyle olması gerektiği gibi görünüyor), Açısal diğer yapısal direktifler için iptal etme yeteneğini nasıl genelleştirmelidir?

Bu soruların kolay cevapları yok. Birden fazla yapısal direktifin yasaklanması onları tartışıyor. Bu kullanım şeklini kolay bir çözümdür var: koymak * ngIf sarar bir kap elemanı üzerinde * ngFor elemanı. Öğelerden biri veya her ikisi de bir kapsayıcı olabilir, bu nedenle fazladan HTML düzeyleri eklemenize gerek yoktur.

Bu nedenle, ng-container(Angular4) öğesini sarmalayıcı olarak (dom'dan silinecek) veya sınıfınız veya aşağıdaki gibi başka nitelikleriniz varsa bir div veya span kullanabilirsiniz:

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

4

Bu işe yarayacaktır, ancak öğe hala DOM'da olacaktır.

.hidden {
    display: none;
}

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

Bu sadece tam liste yerine filtrelenmiş öğeleri göstermek istiyorum <select> <option> kombinasyonu için çok kolay bir kesmek
davyzhang

Çok teşekkür ederim!
Abhishek Sharma

3

Aşağıdaki tabloda yalnızca "başlangıç" değeri ayarlanmış öğeler listelenmektedir. HTML'de istenmeyen satırları önlemek için hem *ngForve hem de gerekir *ngIf.

Başlangıçta *ngIfve *ngForaynı <tr>etikette vardı, ancak çalışmıyor. Bir eklendi <div>için *ngFordöngü ve yerleştirilen *ngIfiçinde <tr>etiketi, beklendiği gibi çalışır.

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

1
<div>Bir tablonun içinin bir goos fikri olduğunu düşünmüyorum , özellikle daha iyi alternatifler olduğunda. Özellikle elementler hakkında seçici olan IE'de çalışıp çalışmadığını kontrol ettiniz mi<table>
Günter Zöchbauer

3

Açısal2 beta 8 olarak güncellendi

Şimdi angular2 beta 8'den itibaren aynı bileşeni kullanabiliriz *ngIfve buraya bakınız .*ngFor

Alternatif:

Bazen HTML etiketlerini in tr, th( table) veya in li( ul) gibi bir başkasının içinde kullanamayız . Başka bir HTML etiketi kullanamayız, ancak HTML5 özellik etiketini <template>bu şekilde yapabilmemiz için aynı durumda bazı işlemler yapmamız gerekir .

Şablon kullanmak için:

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

ng Şablon kullanıyorsanız:

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

Açısal2'deki yapısal direktifler hakkında daha fazla bilgi için buraya bakınız .


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

1

Ayrıca kullanabilirsiniz ng-template(. Yerine şablonun şablon etiketi kullanımına ilişkin uyarı için nota bakın) hem uygulamak için * ngFor ve ngIf aynı HTML elemanı üzerinde. Açısal tabloda aynı tr öğesi için hem * ngIf hem de * ngFor kullanabileceğiniz bir örnek .

<tr *ngFor = "let fruit of fruiArray">
    <ng-template [ngIf] = "fruit=='apple'>
        <td> I love apples!</td>
    </ng-template>
</tr>

nerede fruiArray = ['apple', 'banana', 'mango', 'pineapple'].

Not:

templateEtiket yerine sadece etiketi kullanmanın uyarısı, bazı yerlerde ng-templateatılmasıdır StaticInjectionError.


0

<!-- Since angular2 stable release multiple directives are not supported on a single element(from the docs) still you can use it like below -->


<ul class="list-group">
                <template ngFor let-item [ngForOf]="stuff" [ngForTrackBy]="trackBy_stuff">
                    <li *ngIf="item.name" class="list-group-item">{{item.name}}</li>
                </template>
   </ul>


li öğeleri yalnızca bir ismi varsa görüntülenir.
Rajiv

3
Bu cevap buraya nasıl değer katıyor? Zaten diğer cevaplar tarafından sağlanmayan hiçbir şey sağlamıyor veya bir şey mi kaçırdım?
Günter Zöchbauer

0

Aynı eleman üzerinde birden fazla yapısal yönerge kullanamazsınız. Öğenizi içine sarın ng-templateve orada bir yapısal yönerge kullanın


0

Dizi uzunluğunu kontrol ederek bunu başka bir şekilde yapabilirsiniz

<div *ngIf="stuff.length>0">
  <div *ngFor="let thing of stuff">
    {{log(thing)}}
    <span>{{thing.name}}</span>
  </div>
</div>

-1

app.component.ts

import {NgModule, Component} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';

@Component({
  selector: 'ngif-example',
  template: `
<h4>NgIf</h4>
<ul *ngFor="let person of people">
  <li *ngIf="person.age < 30"> (1)
  {{ person.name }} ({{ person.age }})
  </li>
</ul>
`
})
class NgIfExampleComponent {

  people: any[] = [
    {
      "name": "yogesh ",
      "age": 35
    },
    {
      "name": "gamesh",
      "age": 32
    },
    {
      "name": " Meyers",
      "age": 21
    },
    {
      "name": " Ellis",
      "age": 34
    },
    {
      "name": " Tyson",
      "age": 32
    }
  ];
}

app.component.html

<ul *ngFor="let person of people" *ngIf="person.age < 30">
  <li>{{ person.name }}</li>
</ul>

Çıktı

Meyers(21)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.