* ngIf else if in template

101

¿Cómo podría tener varios casos en una *ngIfdeclaración? Estoy acostumbrado a que Vue o Angular 1 tenga un if, else ify else, pero parece que Angular 4 solo tiene una condición true( if) y false( else).

Según la documentación, solo puedo hacer:

  <ng-container *ngIf="foo === 1; then first else second"></ng-container>
  <ng-template #first>First</ng-template>
  <ng-template #second>Second</ng-template>
  <ng-template #third>Third</ng-template>

Pero quiero tener múltiples condiciones (algo como):

  <ng-container *ngIf="foo === 1; then first; foo === 2; then second else third"></ng-container>
  <ng-template #first>First</ng-template>
  <ng-template #second>Second</ng-template>
  <ng-template #third>Third</ng-template>

Pero termino teniendo que usar ngSwitch, lo que se siente como un truco:

  <ng-container [ngSwitch]="true">
    <div *ngSwitchCase="foo === 1">First</div>
    <div *ngSwitchCase="bar === 2">Second</div>
    <div *ngSwitchDefault>Third</div>
  </ng-container>

Alternativamente, parece que muchas de las sintaxis a las que me he acostumbrado de Angular 1 y Vue no son compatibles con Angular 4, entonces, ¿cuál sería la forma recomendada de estructurar mi código con condiciones como esta?

Alexander Abakumov
fuente
Estaba pensando que hackear era la mejor solución ya que era más legible. Sin embargo, me he dado cuenta de que las declaraciones de cambio angular permiten que coincidan varios criterios, por lo que no obtiene esa verdadera lógica elseif.
Tom Benyon

Respuestas:

145

Otra alternativa es anidar las condiciones.

<ng-container *ngIf="foo === 1;else second"></ng-container>
<ng-template #second>
    <ng-container *ngIf="foo === 2;else third"></ng-container>
</ng-template>
<ng-template #third></ng-template>
CornelC
fuente
4
Esta fue la mejor solución para mí. Mis condiciones se basaron en múltiples variables y más de una podían ser verdaderas al mismo tiempo.
Matt DeKok
1
¿No podemos usar como?<ng-template #second *ngIf="foo === 2;else third">
Loki
inteligente. debe ser introducido al marco
tbh
36

Puedes usar:

<ng-template [ngIf]="index == 1">First</ng-template>
<ng-template [ngIf]="index == 2">Second</ng-template>
<ng-template [ngIf]="index == 3">Third</ng-template>

a menos que la parte ng-container sea importante para su diseño, supongo.

Aquí hay un Plunker

Dylan
fuente
1
Mi ejemplo es un poco simplista, pero esperando el comportamiento 'else if' tal que if (index === 1) else if (foo === 2)tendría que escribirse, if (index === 1) if (index !== 1 && foo === 2)que es un poco desordenado y más propenso a errores, más veces tenemos que escribir lógica inversa.
¿Has mirado el plunker? No creo que vea el problema, el índice solo será una cosa a la vez.
Dylan
Creo que es mi ejemplo el que carece de explicación, aquí hay un ejemplo en JS: if (item === 'food' && kind === 'hamburger') {} else if (item === 'food' && kind === 'hotdog') {} else if (item === 'drink' && kind === 'beer') {} else if (item === 'drink' && kind === 'wine') {} else { /* could be poisonous */ }
1
Todavía hay demasiada exclusión mutua en ese ejemplo, pero aún así, el punto es que tengo que hacer si, si no, y si no, no solo si y si no sin escribir toneladas de lógica redundante. Parece que las plantillas de Angular 4 carecen de este tipo de lógica.
1
hay algunas otras opciones, esto parece que puede beneficiarse de un NgTemplateOutletcontexto con como * ngTemplateOutlet = "beber; contexto: cerveza", o tal vez otro componente para categorizar.
Dylan
26

Esta parece ser la forma más limpia de hacer

if (foo === 1) {

} else if (bar === 99) {

} else if (foo === 2) {

} else {

}

en la plantilla:

<ng-container *ngIf="foo === 1; else elseif1">foo === 1</ng-container>
<ng-template #elseif1>
    <ng-container *ngIf="bar === 99; else elseif2">bar === 99</ng-container>
</ng-template>
<ng-template #elseif2>
    <ng-container *ngIf="foo === 2; else else1">foo === 2</ng-container>
</ng-template>
<ng-template #else1>else</ng-template>

Tenga en cuenta que funciona como else ifdebería funcionar una declaración adecuada cuando las condiciones involucran diferentes variables (solo 1 caso es verdadero a la vez). Algunas de las otras respuestas no funcionan bien en tal caso.

aparte: Dios angular, ese es un else ifcódigo de plantilla realmente feo ...

cabra
fuente
17

Puede usar múltiples formas según la situación:

  1. Si su Variable está limitada a un Número o Cadena específicos , la mejor manera es usar ngSwitch o ngIf:

    <!-- foo = 3 -->
    <div [ngSwitch]="foo">
        <div *ngSwitchCase="1">First Number</div>
        <div *ngSwitchCase="2">Second Number</div>
        <div *ngSwitchCase="3">Third Number</div>
        <div *ngSwitchDefault>Other Number</div>
    </div>
    
    <!-- foo = 3 -->
    <ng-template [ngIf]="foo === 1">First Number</ng-template>
    <ng-template [ngIf]="foo === 2">Second Number</ng-template>
    <ng-template [ngIf]="foo === 3">Third Number</ng-template>
    
    
    <!-- foo = 'David' -->
    <div [ngSwitch]="foo">
        <div *ngSwitchCase="'Daniel'">Daniel String</div>
        <div *ngSwitchCase="'David'">David String</div>
        <div *ngSwitchCase="'Alex'">Alex String</div>
        <div *ngSwitchDefault>Other String</div>
    </div>
    
    <!-- foo = 'David' -->
    <ng-template [ngIf]="foo === 'Alex'">Alex String</ng-template>
    <ng-template [ngIf]="foo === 'David'">David String</ng-template>
    <ng-template [ngIf]="foo === 'Daniel'">Daniel String</ng-template>
    
  2. Lo anterior no es adecuado para códigos if elseif else y códigos dinámicos, puede usar el siguiente código:

    <!-- foo = 5 -->
    <ng-container *ngIf="foo >= 1 && foo <= 3; then t13"></ng-container>
    <ng-container *ngIf="foo >= 4 && foo <= 6; then t46"></ng-container>
    <ng-container *ngIf="foo >= 7; then t7"></ng-container>
    
    <!-- If Statement -->
    <ng-template #t13>
        Template for foo between 1 and 3
    </ng-template>
    <!-- If Else Statement -->
    <ng-template #t46>
        Template for foo between 4 and 6
    </ng-template>
    <!-- Else Statement -->
    <ng-template #t7>
        Template for foo greater than 7
    </ng-template>
    

Nota: puede elegir cualquier formato, pero tenga en cuenta que cada código tiene sus propios problemas

Sina Lotfi
fuente
1
En mi opinión 2. debería leer en *ngIf="foo >= 7; then t7"lugar de ... else t7.
hgoebl
Creo que solo dos líneas con la segunda foo >= 4 && foo <= 6; then t46; else t7deberían funcionar.
Cloud
4

Para evitar el anidamiento y ngSwitch, también existe esta posibilidad, que aprovecha la forma en que los operadores lógicos funcionan en Javascript:

<ng-container *ngIf="foo === 1; then first; else (foo === 2 && second) || (foo === 3 && third)"></ng-container>
  <ng-template #first>First</ng-template>
  <ng-template #second>Second</ng-template>
  <ng-template #third>Third</ng-template>
Max21
fuente
0

<ion-row *ngIf="cat === 1;else second"></ion-row>
<ng-template #second>
    <ion-row *ngIf="cat === 2;else third"></ion-row>
</ng-template>
<ng-template #third>

</ng-template>

Angular ya está usando ng-template bajo el capó en muchas de las directivas estructurales que usamos todo el tiempo: ngIf, ngFor y ngSwitch.

> ¿Qué es ng-template en Angular?

https://www.angularjswiki.com/angular/what-is-ng-template-in-angular/

Supriya
fuente
0

También puede usar este viejo truco para convertir bloques complejos if / then / else en una declaración de cambio ligeramente más limpia:

<div [ngSwitch]="true">
    <button (click)="foo=(++foo%3)+1">Switch!</button>

    <div *ngSwitchCase="foo === 1">one</div>
    <div *ngSwitchCase="foo === 2">two</div>
    <div *ngSwitchCase="foo === 3">three</div>
</div>
Michael Payne
fuente