0

I have a functioning ngSwitch

<div class="columnFormatting" [ngSwitch]="statusIds">
  <div *ngSwitchCase="2"> Do 2 </div>
  <div *ngSwitchCase="4"> Do 4 </div>
  <div *ngSwitchDefault> Default </div>
</div>

StatusIds can contain one or more integers separated by commas.

If statusIds is [2,4] I want it to hit both cases. Is this possible without a foreach loop outside of the switch?

Andrew Fraser
  • 78
  • 2
  • 9

2 Answers2

0

ngSwitch only takes single value,but in order to display multiple cases you can do the following.

<div class="columnFormatting" *ngFor="let status of statusIds" [ngSwitch]="status">
  <div *ngSwitchCase="2"> Do 2 </div>
  <div *ngSwitchCase="3"> Do 4 </div>
  <div *ngSwitchDefault> Default </div>
</div>

With the combination of ngFor and ngSwitch you can achieve what you asked. You don't need to have a for loop outside the switch,you can have along with switch as I mentioned above.

For further reference

I hope this will help you. If you have any problems or suggestions let me know.

Suvethan Nantha
  • 2,404
  • 16
  • 28
  • Hi nice answer but not showing proper output if it's dropdown based value selection.. For ex. I have one dropdown from which I select value and based on that selection I want to show another dropdown..it's working for single .. I create same another row for dropdown selection so it's not working a sit contains array of object values – sda87 Oct 28 '22 at 14:09
0

This is old, but I was hunting for this answer and wound up looking up the ngSwitchCase code and creating an array version. Angular uses basically this code to check each ngSwitchCase via the DoCheck & within the ngSwitch a call to _matchCase(value), also noticed the code plays with index counts, so for each item in the array you need to create an object or validate it yourself outside the list. Which is how I created this one.

import { NgSwitch } from '@angular/common';
import {Directive, DoCheck, Host, Input, OnInit, Optional, TemplateRef, ViewContainerRef, ɵRuntimeError as RuntimeError} from '@angular/core';

@Directive({
    selector: '[ngSwitchCaseArray]'
  })
  export class NgSwitchCaseArray implements DoCheck {
    private _view: SwitchView;
    /**
     * Stores the HTML template to be selected on match.
     */
    @Input() ngSwitchCaseArray: any[] = [];
  
    constructor(
        viewContainer: ViewContainerRef, templateRef: TemplateRef<Object>,
        @Optional() @Host() private ngSwitch: NgSwitch) {
        if (!ngSwitch) { // make sure we have a host
            throwNgSwitchProviderNotFoundError('ngSwitchCaseArray', 'NgSwitchCaseArray');
        }
        
      this._view = new SwitchView(viewContainer, templateRef);
      // either we add a case for each time we call ngSwitch._matchCase
      // or we only add one case and call matchcase once per check
      (this.ngSwitch as any)._addCase();
    }
  
    // this is how the ngSwitchCase works, just call's ngSwitch._matchCase(item) when true we're supposed to do something
    ngDoCheck() {
      this._view.enforceState(this.matchCase());
    }

    matchCase(): boolean {
      // advantage of us finding the item in our array, is we're not calling matchCase which requires 1 addCase per call
      //   so if the array changes it wont break the case code we initialize with
      var switchValue = (this.ngSwitch as any)._ngSwitch; // this is the value passed into ngSwitch
      var index = this.ngSwitchCaseArray.indexOf(switchValue); // grab index, jic value is null, undefined, etc.
      var item: any = this.ngSwitchCaseArray; // pass the array as default, should fail in most cases
      if (index != -1) item = this.ngSwitchCaseArray[index]; // get the actual value if we found an index
      return (this.ngSwitch as any)._matchCase(item); // MUST call _matchCase once and only once or you break ngSwitch
    }
  }

  // stuff below was copied from angular/packages/common/src/directives/ng_switch.ts 
  class SwitchView {
    private _created = false;
  
    constructor(
        private _viewContainerRef: ViewContainerRef, private _templateRef: TemplateRef<Object>) {}
  
    create(): void {
      this._created = true;
      this._viewContainerRef.createEmbeddedView(this._templateRef);
    }
  
    destroy(): void {
      this._created = false;
      this._viewContainerRef.clear();
    }
  
    enforceState(created: boolean) {
      if (created && !this._created) {
        this.create();
      } else if (!created && this._created) {
        this.destroy();
      }
    }
  }

  function throwNgSwitchProviderNotFoundError(attrName: string, directiveName: string): never {
    throw new RuntimeError(
        2000, //RuntimeErrorCode.PARENT_NG_SWITCH_NOT_FOUND,
        `An element with the "${attrName}" attribute ` +
            `(matching the "${
                directiveName}" directive) must be located inside an element with the "ngSwitch" attribute ` +
            `(matching "NgSwitch" directive)`);
  }

Then you just need some code for it to work:

<div *ngSwitch="objectValue">
    <div *ngSwitchCase="abc">abc found</div>
    <div *ngSwitchCaseArray="[ 'value', 'Value', null, 'Blah', 'etc.' ]">Found something in the array</div>
    <div *ngSwitchDefault>Nothing found</div>
</div>
Vince
  • 757
  • 1
  • 8
  • 16