* ngSe se estiver no modelo

101

Como eu teria vários casos em uma *ngIfdeclaração? Estou acostumado a Vue ou angular 1 com ter um if, else ife else, mas parece que Angular 4 tem apenas uma true( if) e false( elsecondição).

De acordo com a documentação, só posso fazer:

  <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>

Mas eu quero ter várias condições (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>

Mas estou acabando tendo que usar ngSwitch, o que parece um hack:

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

Como alternativa, parece que muitas das sintaxes com as quais me acostumei do Angular 1 e Vue não são suportadas no Angular 4, então qual seria a maneira recomendada de estruturar meu código com condições como essa?

Alexander Abakumov
fonte
Eu estava pensando que o seu hack era a melhor solução, pois era mais legível. No entanto, percebi que as instruções de switch angular permitem a correspondência de vários critérios, de modo que você não obtém a verdadeira lógica elseif.
Tom Benyon

Respostas:

144

Outra alternativa é aninhar condições

<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
fonte
4
Essa foi a melhor solução para mim. Minhas condições eram baseadas em múltiplas variáveis ​​e mais de uma eram capazes de ser verdadeiras ao mesmo tempo.
Matt DeKok,
1
Não podemos usar como<ng-template #second *ngIf="foo === 2;else third">
Loki
inteligente. deve ser apresentado ao framework tbh
Pogrindis
36

Você pode apenas 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 a parte ng-container seja importante para seu projeto, suponho.

Aqui está um Plunker

Dylan
fonte
1
Meu exemplo é um pouco simplista, mas esperando o comportamento 'else if' tal que if (index === 1) else if (foo === 2)teria que ser escrito, o if (index === 1) if (index !== 1 && foo === 2)que é um pouco confuso e mais sujeito a erros, mais vezes temos que escrever a lógica inversa.
Você já olhou para o êmbolo? Acho que não vejo o problema, o índice será apenas uma coisa de cada vez.
Dylan
Acho que é meu exemplo que falta explicação, aqui está um exemplo em 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
Ainda há muita exclusão mútua naquele exemplo, mas ainda assim, o ponto é, eu preciso fazer if, else if, e else, não apenas if e else sem escrever toneladas de lógica redundante. Parece que os modelos do Angular 4 carecem desse tipo de lógica.
1
existem algumas outras opções, parece que você pode se beneficiar de um NgTemplateOutletcontexto como * ngTemplateOutlet = "bebida; contexto: cerveja" ou talvez outro componente para categorização.
Dylan
26

Esta parece ser a maneira mais limpa de fazer

if (foo === 1) {

} else if (bar === 99) {

} else if (foo === 2) {

} else {

}

no modelo:

<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>

Observe que funciona como uma else ifinstrução apropriada deveria quando as condições envolvem variáveis ​​diferentes (apenas 1 caso é verdadeiro por vez). Algumas das outras respostas não funcionam bem nesse caso.

à parte: nossa angular, isso é um else ifcódigo de modelo realmente feio ...

bode
fonte
17

Você pode usar várias formas com base na situação:

  1. Se sua variável for limitada a um número ou string específico , a melhor maneira é usar ngSwitch ou 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. Acima não é adequado para códigos if elseif e códigos dinâmicos, você pode usar o código abaixo:

    <!-- 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: Você pode escolher qualquer formato, mas observe que cada código tem seus próprios problemas

Sina Lotfi
fonte
1
IMO 2. deve ler em *ngIf="foo >= 7; then t7"vez de ... else t7.
hgoebl
Acho que apenas duas linhas com a segunda sendo foo >= 4 && foo <= 6; then t46; else t7devem funcionar.
Nuvem
4

Para evitar aninhamento e ngSwitch, também existe esta possibilidade, que aproveita a maneira como os operadores lógicos funcionam em 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
fonte
2

Ou talvez apenas use cadeias condicionais com operador ternário. if … else if … else if … elsecorrente.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator#Conditional_chains

<ng-container *ngIf="isFirst ? first: isSecond ? second : third"></ng-container>

<ng-template #first></ng-template>
<ng-template #second></ng-template>
<ng-template #third></ng-template>

Eu gosto mais dessa abordagem.

Gerald Hughes
fonte
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 já está usando ng-template por baixo do capô em muitas das diretivas estruturais que usamos o tempo todo: ngIf, ngFor e ngSwitch.

> O que é ng-template no Angular

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

Supriya
fonte
0

Você também pode usar este velho truque para converter blocos if / then / else complexos em uma instrução switch um pouco mais limpa:

<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
fonte