Hay un documento bastante bueno sobre el uso de * ngIf en Angular: https://angular.io/api/common/NgIf Pero, ¿es posible tener * ngIf variable asíncrona y múltiples comprobaciones? Algo como:
<div *ngIf="users$ | async as users && users.length > 1"> ... </div>Por supuesto, es posible usar *ngIf anidado, como:
<div *ngIf="users$ | async as users"> <ng-container *ngIf="users.length > 1"> ... </ng-container> </div>pero sería muy bueno usar solo un contenedor, no dos.
Puedes hacerlo:
<ng-template ngFor let-user [ngForOf]="users$ | async" *ngIf="(users$ | async)?.length > 1 && (users$ | async)?.length < 5"> <div>{{ user | json }}</div> </ng-template>Tenga en cuenta que al usar una suscripción de una solicitud http, esto activaría la solicitud dos veces. Por lo tanto, debe usar algún patrón o biblioteca de administración de estado para que eso no suceda.
Aquí hay un stackblitz .
Me encontré con el mismo problema de necesitar una variable asíncrona * ngIf + con múltiples comprobaciones.
Esto terminó funcionando bien para mí.
<div *ngIf="(users$ | async)?.length > 0 && (users$ | async) as users"> ... </div>o si lo prefieres
<div *ngIf="(users$ | async)?.length > 0 && (users$ | async); let users"> ... </div>Explicación
Dado que el resultado de la expresión if se asigna a la variable local que especifique, simplemente finalice su verificación con ... && (users$ | async) as users le permiten especificar múltiples condiciones y especificar qué valor desea que contenga la variable local cuando todas tus condiciones tengan éxito.
Nota
Inicialmente, me preocupaba que el uso de múltiples canalizaciones async en la misma expresión pudiera crear varias suscripciones, pero después de algunas pruebas ligeras (podría estar equivocado), parece que solo se realiza una suscripción.
Veo que todos usan *ngFor y *ngIf juntos en una etiqueta y soluciones similares, pero creo que es un antipatrón . En la mayoría de los lenguajes de codificación regulares, no haces una instrucción if y un bucle for en la misma línea, ¿verdad? En mi humilde opinión, si tienes que trabajar porque ellos específicamente no quieren que lo hagas, se supone que no debes hacerlo. No practique lo que no es "la mejor práctica".
✅✅✅ Mantenlo simple, si no necesitas declarar el $valor implícito de users$ | async como usuarios:
<!-- readability is your friend --> <div *ngIf="(users$ | async).length > 1"> ... </div> Pero si necesita declararse as user , envuélvalo.
✅ Para casos de uso complejo; Eso sí, el marcado generado ni siquiera tendrá una etiqueta HTML, ¡esa es la belleza de ng-templates y ng-containers!
La respuesta editada y aceptada de @alsami funciona porque * ngFor con asterisco es una abreviatura de ng-template con ngFor (sin asterisco), sin mencionar la doble tubería asíncrona 🙏 . El código realmente huele a inconsistencia cuando combinas un ngFor sin asterisco con un *ngIf; entiendes la esencia. El *ngIf tiene prioridad, así que ¿por qué no simplemente envolverlo en un contenedor ng/plantilla ng? No envolverá sus elementos internos usando una etiqueta HTML en el marcado generado.
<div *ngIf="users$ | async as prods; then thenB; else elseB"></div> <ng-template #thenB> <!-- inner logic --> <div *ngIf="prods?.length > 1 && users?.length < 5; else noMatchB"> Loaded and inbound </div> <ng-template #noMatchB>Loaded and out of bound</ng-template> </ng-template> <ng-template #elseB>Content to render when condition is false.</ng-template>❌ No hagas esto
<!-- Big NO NO --> <div *ngIf="(users$ | async)?.length > 1 && (users$ | async)?.length < 5"> ... </div>Las tuberías son un poco intimidantes después de conocer su sensibilidad a los ciclos de vida; se actualizan como locos. Es por eso que Angular NO tiene SortPipe ni FilterPipe. Entonces, erm, no hagas esto; básicamente está creando 2 Observables que a veces se actualizan frenéticamente y pueden causar una falta de coincidencia de datos a largo plazo en sus hijos si estoy en lo correcto.