Cómo comprobar la longitud de una matriz observable

109

En mi componente Angular 2 tengo una matriz observable

list$: Observable<any[]>;

En mi plantilla tengo

<div *ngIf="list$.length==0">No records found.</div>

<div *ngIf="list$.length>0">
    <ul>
        <li *ngFor="let item of list$ | async">item.name</li>
    </ul>
</div>

Pero list $ .length no funciona en el caso de una matriz observable.

Actualizar:

Parece que (list $ | async) ?. length nos da la longitud, pero el siguiente código aún no funciona:

<div>
    Length: {{(list$ | async)?.length}}
    <div *ngIf="(list$ | async)?.length>0">
        <ul>
            <li *ngFor="let item of (list$ | async)">
                {{item.firstName}}
            </li>
        </ul>
    </div>
</div>

¿Alguien puede orientarme sobre cómo verificar la longitud de la matriz observable?

Naveed Ahmed
fuente
Reportado en github.com/angular/angular/issues/9641
Günter Zöchbauer

Respuestas:

178

Puedes usar la | asynctubería:

<div *ngIf="(list$ | async)?.length==0">No records found.</div>

Actualización - Versión angular 6:

Si está cargando un esqueleto css, puede usar esto. Si la matriz no tiene elementos, mostrará la plantilla css. Si hay datos, complete el ngFor.

<ul *ngIf="(list$| async)?.length > 0; else loading">
   <li *ngFor="let listItem of list$| async">
      {{ listItem.text }}
   </li>
</ul>

<ng-template #loading>
  <p>Shows when no data, waiting for Api</p>
  <loading-component></loading-component>
</ng-template>
Günter Zöchbauer
fuente
4
Lo intenté también, pero da el error "TypeError: No se puede leer la propiedad 'longitud' de nulo"
Naveed Ahmed
3
Es difícil saberlo por la información que proporcionó. Try <div *ngIf="(list$ | async)?.length==0">No records found.</div>(agregado ?)
Günter Zöchbauer
6
Intenté esto y funciona <div * ngIf = "(list $ | async) ?. length == 0"> No se encontraron registros. </div>
Naveed Ahmed
3
El adicional ?es obligatorio porque list$solo se establece después de que Angular2 intenta renderizar la vista por primera vez. ?impide que se evalúe el resto de la subexpresión hasta que la parte que queda a la izquierda se ?convierta en != null(Elvis u operador de navegación segura).
Günter Zöchbauer
1
@ GünterZöchbauer me parece que esa primera asynctubería resuelve datos y, por lo tanto, mi próxima asynctubería en el bucle no muestra nada. O tal vez *ngIfcrea un alcance adicional y, por lo tanto, no funciona. Difícil de decir. Pero mientras mi bucle está envuelto dentro, no muestra ningún dato. Si se evalúa truecorrectamente.
Eugene
31

Una solución para .ts-Files:

     this.list.subscribe(result => {console.log(result.length)});
Blanco
fuente
¿No es necesario darse de baja inmediatamente después?
Peter
Es mejor darse de baja de los observables en el onDestroycomponente
ThPadelis
16

Para Angular 4+, prueba esto

<div *ngIf="list$ | async;let list">
    Length: {{list.length}}
    <div *ngIf="list.length>0">
        <ul>
            <li *ngFor="let item of list">
                {{item.firstName}}
            </li>
        </ul>
    </div>
</div>
MD KAMRUL HASAN SHAHED
fuente
7

Si bien esta respuesta es correcta

<div *ngIf="(list$ | async)?.length === 0">No records found.</div>

Tenga en cuenta que si está utilizando un cliente http para llamar al backend (en la mayoría de los casos lo hace), obtendrá llamadas duplicadas a su API si tiene más de una lista $ | async . Esto se debe a que cada | async pipe creará un nuevo suscriptor a su lista $ observable.

Andzej Maciusovic
fuente
4

Esto es lo que funcionó para mí:

*ngIf="!photos || photos?.length===0"

Obtengo mis datos de httpClient async.

Todas las otras opciones aquí no funcionaron para mí, lo cual fue decepcionante. Especialmente la tubería sexy (list $ | async).

Basa ..

Tzvi Gregory Kaidanov
fuente
2

Su enfoque aquí tiene otro problema importante: al aprovechar la tubería asíncrona una y otra vez en su plantilla, en realidad está iniciando tantas suscripciones al único Observable.

KAMRUL HASAN SHAHED tiene el enfoque correcto anterior: use la tubería asíncrona una vez y luego proporcione un alias para el resultado que puede aprovechar en los nodos secundarios.

Harry Beckwith
fuente
1

También se puede acortar:

<div *ngIf="!(list$ | async)?.length">No records found.</div>

Simplemente use el signo de exclamación antes del paréntesis.

Daniyal Lukmanov
fuente
-3

iónico 4

<div *ngIf="(items | async)?.length==0">No records found.</div>

funcionó cuando quité el $letrero

Ahmed Al-hajri
fuente