Tengo un problema al tratar de usar Angular's *ngFor
y *ngIf
en el mismo elemento.
Al intentar recorrer la colección en el *ngFor
, la colección se ve como null
y, en consecuencia, falla al intentar acceder a sus propiedades en la plantilla.
@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);
}
}
Sé que la solución fácil es subir el *ngIf
nivel, pero para escenarios como recorrer los elementos de la lista en un ul
, terminaría con un vacío li
si la colección está vacía, o mi li
s envuelto en elementos contenedores redundantes.
Ejemplo en este plnkr .
Tenga en cuenta el error de la consola:
EXCEPTION: TypeError: Cannot read property 'name' of null in [{{thing.name}} in ShellComponent@5:12]
¿Estoy haciendo algo mal o es un error?
angular
ngfor
angular-ng-if
garethdn
fuente
fuente
Respuestas:
Angular v2 no admite más de una directiva estructural sobre el mismo elemento.
Como solución alternativa, use el
<ng-container>
elemento que le permite usar elementos separados para cada directiva estructural, pero no está estampado en el DOM .<ng-template>
(<template>
antes de Angular v4) permite hacer lo mismo pero con una sintaxis diferente que es confusa y ya no se recomiendafuente
ngFor
el<ng-container>
elemento y elngIf
en el<div>
. También puede tener dos anidados<ng-container>
envolviendo el<div>
.<ng-container>
es solo un elemento auxiliar que no se agregará al DOM.<ng-container>
. Se comporta igual<template>
pero permite utilizar la sintaxis "normal" para directivas estructurales.Como todos señalaron, aunque tener múltiples directivas de plantilla en un solo elemento funciona en angular 1.x, no está permitido en Angular 2. Puede encontrar más información aquí: https://github.com/angular/angular/issues/ 7315
2016 angular 2 beta
la solución es usar el
<template>
como marcador de posición, por lo que el código es asípero por alguna razón anterior no funciona
2.0.0-rc.4
en ese caso, puede usar estoRespuesta actualizada 2018
Con actualizaciones, ahora en 2018 angular v6 se recomienda usar en
<ng-container>
lugar de<template>
Así que aquí está la respuesta actualizada.
fuente
Como @Zyzle mencionó y @ Günter mencionó en un comentario ( https://github.com/angular/angular/issues/7315 ), esto no es compatible.
Con
no hay
<li>
elementos vacíos cuando la lista está vacía. Incluso el<ul>
elemento no existe (como se esperaba).Cuando se llena la lista, no hay elementos contenedores redundantes.
La discusión de github (4792) que @Zyzle mencionó en su comentario también presenta otra solución usando
<template>
(a continuación estoy usando su marcado original - usando<div>
s):Esta solución tampoco introduce ningún elemento contenedor adicional / redundante.
fuente
<template>
es la forma de agregar un elemento padre que no aparecerá en la salida.en html:
en css:
fuente
No se puede tener
ngFor
yngIf
en el mismo elemento. Lo que podría hacer es esperar para completar la matriz en la que está utilizandongFor
hasta que se haga clic en la palanca de su ejemplo.Aquí hay una forma básica (no excelente) de hacerlo: http://plnkr.co/edit/Pylx5HSWIZ7ahoC7wT6P
fuente
you can't
que no es realmente una buena respuesta, ¿no está de acuerdo?No puede usar más de uno
Structural Directive
en Angular en el mismo elemento, crea una mala confusión y estructura, por lo que debe aplicarlos en 2 elementos anidados separados (o puede usarng-container
), lea esta declaración del equipo de Angular:Por lo tanto, puede usar
ng-container
(Angular4) como el contenedor (se eliminará del dom) o un div o span si tiene clase u otros atributos como se muestra a continuación:fuente
Esto funcionará pero el elemento seguirá en el DOM.
fuente
La siguiente tabla solo enumera los elementos que tienen un conjunto de valores "principiante". Requiere tanto el
*ngFor
y el*ngIf
para evitar filas no deseadas en html.Originalmente tenía
*ngIf
y*ngFor
en la misma<tr>
etiqueta, pero no funciona. Se agregó un<div>
para el*ngFor
bucle y se colocó*ngIf
en la<tr>
etiqueta, funciona como se esperaba.fuente
<div>
dentro de una mesa sea una buena idea, especialmente cuando hay mejores alternativas. ¿Ha comprobado si funciona tanto en IE que es especialmente exigente con elementos en<table>
Actualizado a angular2 beta 8
Ahora a partir de angular2 beta 8 podemos usar
*ngIf
y*ngFor
en el mismo componente ver aquí .Alterno:
A veces no podemos usar etiquetas HTML dentro de otra como in
tr
,th
(table
) o inli
(ul
). No podemos usar otra etiqueta HTML, pero tenemos que realizar alguna acción en la misma situación para que podamos etiquetar la función HTML5<template>
de esta manera.ng Para usar la plantilla:
ng Si usa la plantilla:
Para obtener más información sobre las directivas estructurales en angular2, consulte aquí .
fuente
fuente
También puede usar
ng-template
(en lugar de plantilla. Consulte la nota sobre la advertencia de usar la etiqueta de plantilla) para aplicar tanto * ngFor como ngIf en el mismo elemento HTML. Aquí hay un ejemplo donde puede usar tanto * ngIf como * ngFor para el mismo elemento tr en la tabla angular.donde
fruiArray = ['apple', 'banana', 'mango', 'pineapple']
.Nota:
La advertencia de usar solo la
template
etiqueta en lugar de lang-template
etiqueta es que arrojaStaticInjectionError
en algunos lugares.fuente
fuente
No puede usar directivas estructurales múltiples en el mismo elemento. Envuelva su elemento
ng-template
y use una directiva estructural allífuente
Puede hacer esto de otra manera comprobando la longitud de la matriz
fuente
app.component.ts
app.component.html
Salida
fuente