Dois valores de caso de comutação em angular

86

Em php e java podemos fazer

case 1:
case 2:
   echo "something";

de modo que quando o valor for 1 ou 2 "alguma coisa" será impresso na tela, estou construindo um aplicativo angular, estou fazendo algo como o abaixo

<div [ngSwitch]="data.type">
  <div *ngSwitchCase="'multi-choice'">FORM 1</div>
  <div *ngSwitchCase="'singe-choice'">FORM 1</div>
  <div *ngSwitchCase="'range'">FORM 2</div>
</div>

O formulário que é usado para escolha única pode ser usado para escolha múltipla, mas eu tentei algo como abaixo para torná-lo mais organizável

<div [ngSwitch]="data.type">
  <div *ngSwitchCase="'multi-choice' || 'singe-choice'">FORM 1</div>
</div>

Minha má sorte não funcionou, alguém pode sugerir a melhor maneira de fazer isso.

Niyaz
fonte
Consulte também github.com/angular/angular/issues/12174
yurzui

Respostas:

137

(In) felizmente você não pode; o ngSwitché bastante “burro” se você olhar para o código-fonte: é apenas um ===entre o valor de caso e o valor da chave. Você tem duas opções, mas ambas estão longe de ser excelentes.

A opção 1 está usando a diretiva *ngSwitchDefault, mas isso só funcionará se todos os seus vários casos forem FORM 1:

<div [ngSwitch]="data.type">
  <div *ngSwitchDefault>FORM 1</div>
  <div *ngSwitchCase="'range'">FORM 2</div>
</div>

A outra opção, que é bastante prolixa, é fazer algo assim:

<div [ngSwitch]="data.type">
  <div *ngSwitchCase="data.type === 'multi-choice' || data.type === 'singe-choice' ? data.type : '' ">FORM 1</div>
  <div *ngSwitchCase="'range'">FORM 2</div>
</div>
Fabio Antunes
fonte
2
Atualmente estou seguindo o primeiro método
Niyaz
12
Vou para o segundo porque o padrão significa outra coisa, obrigado por essa ideia!
Sebastien DErrico
3
Estou jogando isso aí, se alguém precisa de orum Switch Case... talvez você precise de um em *ngIfvez de um switch: \
MoshMage
A segunda abordagem é incrível.
khichar.anil
3
Pode ser melhorado:*ngSwitchCase="['multi-choice', 'singe-choice'].includes(data.type) ? data.type : '' "
Maiko Kingma
60

Você também pode usar o seguinte, que é muito mais flexível. Você pode então colocar qualquer coisa que seja avaliada como booleana como o valor * ngSwitchCase.

<div [ngSwitch]="true">
    <div *ngSwitchCase="data.type === 'multi-choice' || data.type === 'singe-choice'">FORM 1</div>
    <div *ngSwitchCase="data.type === 'range'">FORM 2</div>
    <div *ngSwitchDefault>FORM 3</div>
</div>

A vantagem disso em relação ao uso de blocos * ngIf é que você ainda pode especificar um padrão.

escapisam
fonte
46

Você pode usar ngTemplateOutletpara implementar isso:

<ng-container [ngSwitch]="variable">
    <ng-container *ngSwitchCase="1">
        <ng-container *ngTemplateOutlet="form1"></ng-container>
    </ng-container>
    <ng-container *ngSwitchCase="2">
        <ng-container *ngTemplateOutlet="form1"></ng-container>
    </ng-container>
    <ng-container *ngSwitchCase="3">FORM 2</ng-container>
    <ng-container *ngSwitchDefault>FORM 3</ng-container>
    <ng-template #form1>FORM 1</ng-template>
</ng-container>
Daniil Palii
fonte
7
Esta é de longe a solução mais limpa e menos hacky. Também é sugerido nos documentos : "Cada instrução switch-case contém um modelo HTML in-line ou referência de modelo"
t.animal
1
Esta solução fornece o resultado mais limpo. Obrigado!
cuddlemeister
1
Uma palavra de advertência: o conteúdo de #form1será renderizado novamente entre switchCase 1 e 2. Para muitos, isso não importa, mas se o componente for complexo, por enquanto é melhor usar um * ngIf.
Jesse
16

Como o MoshMage sugeriu, acabei usando um *ngIfpara lidar com isso para os componentes que lidavam com várias das opções:

 *ngIf="['Transformation', 'Field Mapping', 'Filter'].includes(selectedWorkflow.type)"
brian3kb
fonte
16

Aqui está uma variação que combina a segunda resposta de Fábio com a de brian3kb para produzir uma solução mais condensada sem ofuscar o significado.

Se houver várias correspondências para um caso, ele usa em array.includes()vez de comparar cada opção individualmente.

É especialmente útil se houver mais de duas correspondências, pois será muito mais condensado em relação à resposta aceita.

<div [ngSwitch]="data.type">
   <div *ngSwitchCase="['multi-choice', 'singe-choice'].includes(data.type) ? data.type : ''">FORM 1</div>
   <div *ngSwitchCase="'range'">FORM 2</div>
   <div *ngSwitchDefault>FORM 3</div>
</div>

Se as correspondências estiverem em uma variável, você pode usar array.indexOf()para evitar o uso do operador ternário condicional.

<div [ngSwitch]="data.type">
  <div *ngSwitchCase="matches[matches.indexOf(data.type)]">FORM 1</div>
  <!-- ... -->
</div>
Daniel Gimenez
fonte
1

Por favor tente ng-switch-when-separator="|"emng-switch

<div ng-switch="temp">
    <div ng-switch-when="1|2" ng-switch-when-separator="|"> echo "something"</div>
</div>
Salman Laei
fonte
5
Observe que esta diretiva é um recurso do AngularJS (aka v1), não do Angular (aka v2 or higher). Embora tenha sido solicitado no passado, ainda não é fornecido em nenhuma versão do Angular 2 até o Angular 9 (na data deste comentário).
NunoM
1

É assim que eu faria:

Em seu .component.ts:

getFormType(type: string) {
  switch(type) {
    case 'singe-choice':
    case 'multi-choice':
      return 'singe-choice|multi-choice'
    default:
      return type;
  }
}

Então, em seu arquivo de modelo, você pode fazer algo assim:

<div [ngSwitch]="getFormType(data.type)">
   <div *ngSwitchCase="'singe-choice|multi-choice'">FORM 1</div>
   <div *ngSwitchCase="'range'">FORM 2</div>
   <div *ngSwitchDefault>FORM 3</div>
</div>

Cuidado com erros de digitação ...

Andrei Cojea
fonte