Sto avendo un problema con il tentativo di usare Angular’s *ngFor
e *ngIf
sullo stesso elemento.
Quando si tenta di eseguire il ciclo attraverso la raccolta in *ngFor
, la raccolta viene considerata null
e di conseguenza non riesce quando si tenta di accedere alle sue proprietà nel modello.
@Component({ selector: 'shell', template: ` Shell
{{log(thing)}} {{thing.name}} ` }) 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); } }
So che la soluzione facile è spostare il livello *ngIf
su un livello, ma per scenari come il loop su elementi di lista in un ul
, mi *ngIf
con un li
vuoto se la raccolta è vuota, o il mio si è avvolto in un contenitore ridondante elementi.
Esempio in questo plnkr .
Notare l’errore della console:
EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in [email protected]:12]
Sto facendo qualcosa di sbagliato o si tratta di un bug?
Angular v2 non supporta più di una direttiva strutturale sullo stesso elemento.
Per ovviare al problema, utilizzare l’elemento
che consente di utilizzare elementi separati per ogni direttiva strutturale, ma non viene stampato sul DOM .
{{log(thing)}} {{thing.name}}
( before Angular v4) permette di fare lo stesso ma con una syntax diversa che è confusa e non più consigliata
{{log(thing)}} {{thing.name}}
Come @Zyzle menzionato e @ Günter menzionato in un commento ( https://github.com/angular/angular/issues/7315 ), questo non è supportato.
Con
- {{log(thing)}} {{thing.name}}
non ci sono elementi
vuoti quando la lista è vuota. Anche l’elemento
non esiste (come previsto).
Quando la lista è popolata, non ci sono elementi del contenitore ridondanti.
La discussione github (4792) che @Zyzle ha menzionato nel suo commento presenta anche un’altra soluzione usando (qui sotto sto usando il tuo markup originale – usando
s):
{{log(thing)}} {{thing.name}}
Questa soluzione inoltre non introduce alcun elemento contenitore aggiuntivo / ridondante.
Come tutti hanno sottolineato, anche se avere più direttive template in un singolo elemento funziona in 1.x angular, non è consentito in Angular 2. puoi trovare maggiori informazioni da qui: https://github.com/angular/angular/issues/ 7315
la soluzione è usare come segnaposto, quindi il codice va così
.....
ma per qualche ragione sopra non funziona in 2.0.0-rc.4
in quel caso puoi usare questo
.....
Con gli aggiornamenti in questo momento nel 2018 angular v6 angular consiglia di utilizzare
invece di
quindi se qui è la risposta aggiornata per gli aggiornamenti angolari più recenti
.....
Ho un’altra soluzione.
Usa [hidden]
invece di *ngIf
La differenza è che *ngIf
rimuoverà l’elemento dal DOM, mentre [hidden]
realtà gioca con lo stile CSS
impostando display: none
Non puoi avere ngFor
e ngIf
sullo stesso elemento. Quello che potresti fare è tenere a bada il popolamento dell’array che stai usando in ngFor
fino a quando non viene cliccato il ngFor
nel tuo esempio.
Ecco un modo semplice (non eccezionale) per farlo: http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P
Funzionerà ma l’elemento sarà ancora nel DOM.
.hidden{ display: none; }
{{log(thing)}} {{thing.name}}
La tabella seguente elenca solo gli elementi con un valore impostato come “principiante”. Richiede sia *ngFor
che *ngIf
per impedire le righe indesiderate in html.
Originariamente aveva *ngIf
e *ngFor
sullo stesso tag
, ma non funziona. Aggiunto un
per il ciclo *ngFor
e posizionato *ngIf
nel tag
, funziona come previsto.
{{lesson.description}} {{lesson.duration}}
Ora come da angular2 beta 8 possiamo usare *ngIf
e *ngFor
sullo stesso componente, vedi qui .
Alternato:
A volte non possiamo usare tag HTML all’interno di un altro come in tr
, th
( table
) o in li
( ul
). Non possiamo usare un altro tag HTML, ma dobbiamo eseguire alcune azioni nella stessa situazione in modo da poter utilizzare il tag in HTML5 in questo modo.
code here....
code here....
Per ulteriori informazioni sulle direttive strutturali in angular2, vedere qui .
Non puoi usare più di una Structural Directive
in Angolare sullo stesso elemento, crea una ctriggers confusione e struttura, quindi devi applicarli in 2 elementi nidificati separati (o puoi usare ng-container
), leggi questa dichiarazione da Angular squadra:
Una direttiva strutturale per elemento host
Un giorno vorrete ripetere un blocco di HTML ma solo quando una particolare condizione è vera. Proverai a mettere sia un * ngFor che un * ngIf sullo stesso elemento host. Angular non ti lascerà. È ansible applicare solo una direttiva strutturale a un elemento.
La ragione è la semplicità. Le direttive strutturali possono fare cose complesse con l’elemento host e i suoi discendenti. Quando due direttive rivendicano lo stesso elemento host, quale ha la precedenza? Quale dovrebbe andare prima, il NgIf o il NgFor? NGF può cancellare l’effetto del NgFor? Se è così (e sembra che dovrebbe essere così), come dovrebbe Angular generalizzare la possibilità di annullare per altre direttive strutturali?
Non ci sono risposte facili a queste domande. Proibire direttive strutturali multiple li rende discutibili. C’è una soluzione semplice per questo caso d’uso: metti * ngIf su un elemento contenitore che racchiude l’elemento * ngFor . Uno o entrambi gli elementi possono essere un ng-container in modo da non dover introdurre livelli extra di HTML.
Quindi puoi usare ng-container
(Angular4) come wrapper (sarà cancellato dal dom) o div o span se hai classi o altri attributi come di seguito:
{{log(thing)}} {{thing.name}}
{{log(thing)}} {{thing.name}}
- {{item.name}}