Two switch case values in angular

Angular

Angular Problem Overview


In php and java we can do

case 1:
case 2:
   echo "something";

so that when the value is 1 or 2 "something" will be printed on the screen, i am building an angular application i am doing something like the below

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

The form which is used for single choice can be used for mutiple choice , but i tried something like below to make it more organisable

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

My bad luck it didnt work, can anyone suggest the better way to do this.

Angular Solutions


Solution 1 - Angular

(Un)fortunately you can‘t; the ngSwitch is quite “dumb” if you look at the source code: it‘s just a === between the case value and the switch value. You have two options, but both of them are far from great.

Option 1 is using the directive *ngSwitchDefault, but this will only work if all your multiple cases are FORM 1:

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

The other option, which is quite verbose, is doing something like this:

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

Solution 2 - Angular

You can use ngTemplateOutlet to implement this:

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

Update

While Angular still considering such feature, there is jonrimmer's switch-cases.directive.ts. Usage example:

<ng-container [ngSwitch]="variable">
    <ng-container *jrSwitchCases="[1, 2]">FORM 1</ng-container>
    <ng-container *ngSwitchCase="3">FORM 2</ng-container>
    <ng-container *ngSwitchDefault>FORM 3</ng-container>
</ng-container>

Solution 3 - Angular

You can also use the following, which is a lot more flexible. You can then put anything that evaluates to boolean as the *ngSwitchCase value.

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

The advantage this has over using *ngIf blocks is that you can still specify a default.

Solution 4 - Angular

Here's a variation that combines Fabio's second answer with brian3kb's to produce a more condensed solution without obfuscating meaning.

If there are multiple matches for a case it uses array.includes() instead of comparing each option individually.

It is especially useful if there are more than two matches as it will be much more condensed relative to the accepted answer.

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

If the matches happen to be in a variable, you can use array.indexOf() to avoid the use of the conditional ternary operator.

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

Solution 5 - Angular

Like MoshMage suggested, I ended up using an *ngIf to handle this for the components that handled several of the options:

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

Solution 6 - Angular

It could be achieved using the ngTemplateOutlet directive:

<ng-container [ngSwitch]="colour">
    <ng-container *ngSwitchCase="'green'">:)</ng-container>
    <ng-container *ngSwitchCase="'yellow'">;)</ng-container>
    <ng-container *ngSwitchCase="'black'" [ngTemplateOutlet]="sad"></ng-container>
    <ng-container *ngSwitchCase="'darkgrey'" [ngTemplateOutlet]="sad"></ng-container>
</ng-container>

<ng-template #sad>:(</ng-template>

Solution 7 - Angular

use ngFor:

<ng-container [ngSwitch]="column">
  <ng-container *ngFor="let numeric of ['case1', 'case2']">
    <ng-container *ngSwitchCase="numeric">
      {{ element[column] | currency }}
    </ng-container>
  </ng-container>
</ng-container>

Solution 8 - Angular

Here's how I would do it:

In your .component.ts:

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

Then, in your template file, you can do something like this:

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

Watch out for typos though...

Solution 9 - Angular

Please try ng-switch-when-separator="|" in ng-switch

<div ng-switch="temp">
    <div ng-switch-when="1|2" ng-switch-when-separator="|"> echo "something"</div>
</div>

Solution 10 - Angular

<ng-container *ngIf="['text', 'email', 'password', 'number'].includes(f.type!)">
    <mat-form-field>
         <mat-label>{{f.placeholder}}</mat-label>
         <input matInput [attr.type]="f.type" [formControlName]="f.name!">
   </mat-form-field>
</ng-container>

Solution 11 - Angular

The Fabio Antunes's second answer, but with a pipe:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'multiSwitchCase',
})
export class MultiSwitchCasePipe implements PipeTransform {
  transform<T = any>(cases: T[], value: T): T {
    return cases.includes(value) ? value : cases[0];
  }
}
<div [ngSwitch]="data.type">
  <div *ngSwitchCase="['multi-choice', 'singe-choice'] | multiSwitchCase: data.type">
    FORM 1
  </div>
</div>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNiyazView Question on Stackoverflow
Solution 1 - AngularFabio AntunesView Answer on Stackoverflow
Solution 2 - AngularDaniil PaliiView Answer on Stackoverflow
Solution 3 - AngularescapisamView Answer on Stackoverflow
Solution 4 - AngularDaniel GimenezView Answer on Stackoverflow
Solution 5 - Angularbrian3kbView Answer on Stackoverflow
Solution 6 - AngularAdrianView Answer on Stackoverflow
Solution 7 - AngularchiloidView Answer on Stackoverflow
Solution 8 - AngularAndrei CojeaView Answer on Stackoverflow
Solution 9 - AngularSalman LaeiView Answer on Stackoverflow
Solution 10 - AngularAhmet EmrebasView Answer on Stackoverflow
Solution 11 - AngularEugene P.View Answer on Stackoverflow