Search code examples
angularng-switch

Angular 9 - ngSwitch not linked


I got a form that is supposed to change according to the case I selected in a dropdown:dropdown taken

The type of the room is taken : simple, doubles or triples.

But, although I read about the ngSwitch to display the DOM (a simple form), I cannot link the 2 (types and the ngSwitch)

According to the logic I found online, I put my HTML code and the condition of the switch in the template from my component.ts (it was in a separate HTML file at first but neither works).

@Component({
  selector: 'app-revenue',
  // templateUrl: './revenue.component.html',
  template: `

    <div [ngSwitch]="types.value">
      <div *ngSwitchDefault="''">
        <p>Essai Espace</p>

          <div>
      <form [formGroup]="revenueForm" (ngSubmit)="revenueManager()">

          <div class="form-group">
          <select name="types" id="types" ngModel="types"  class="form-control"  formControlName="types">
            <option *ngFor="let type of types" [ngValue]="type.value">
              {{type.viewValue}}
            </option>
          </select>
          </div>
      </form>
          <pre>{{revenueForm.value | json }}</pre>
        </div>
      </div>

      <div *ngSwitchCase="'roomsSimples'">
        <p>Essai Espace</p>

        <form [formGroup]="revenueForm" (ngSubmit)="revenueManager()">

        <div class="form-group">
            <label>Rooms Simples</label>
            <input type="text" class="form-control" formControlName="roomsSimples">
          </div>

          <button type="submit" class="btn btn-primary">OK</button>

        <div>

          <div class="form-group">
            <select name="types" id="types" ngModel="types"  class="form-control"  formControlName="types">
              <option *ngFor="let type of types" [ngValue]="type.value">
                {{type.viewValue}}
              </option>
            </select>
          </div>
        </div>
        </form>
        <pre>
    {{revenueForm.value | json }}
    </pre>
      </div>
  `,

  styleUrls: ['./revenue.component.sass']
})

I have declared in my class the types:

export class RevenueComponent implements OnInit {
  revenueForm: FormGroup;

  // doubles = value.roomsDoubles;
  header = "Outils Revenus";

  //Pour les rooms
  types = [
    {value: 'roomsSimples', viewValue: 'Rooms Simples'},
    {value: 'roomsDoubles', viewValue: 'Rooms Doubles'},
  ];
  // type = this.types.values();

  constructor(private fb: FormBuilder) {
  }

  ngOnInit(): void {
    this.revenueForm = this.fb.group({
      roomsDoubles: [],
      roomsDoublesEnfant: [],
      roomsTriples: [],
      roomsAppartement: [],
      types: [],
    })
  }

  revenueManager() {
    console.log('Données du formulaire...', this.revenueForm.value);
  }
}

Though the value of types appears on my render, the modification of the DOM doesn't appear. Can you please direct me on the right track? Thanks


Solution

  • In [ngSwitch]="types.value" types is an Array and not an Object, so doing types.value will not work types can only be accessed by index e.g types[0].value

    From your code it is not very clear what you are attempting to achieve but it looks like you have some logic problem in the way you are organizing the component that goes beyond just the use of ngSwitch.

    Here is an example of using ngSwitch in the context of what I understand you want to achieve.

    component.ts

    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      selectedRoomType: any;
      types = [
        {value: 'roomsSimples', viewValue: 'Rooms Simples'},
        {value: 'roomsDoubles', viewValue: 'Rooms Doubles'},
      ];
    }
    

    component.html

    <!-- Dropdown to select the room type -->
    <mat-form-field appearance="fill">
      <mat-label>Room Types</mat-label>
    
      <!-- Bind the selection to selectedRoomType -->
      <mat-select [(value)]="selectedRoomType" >
        <mat-option *ngFor="let type of types" [value]="type.value">
          {{type.viewValue}}
        </mat-option>
      </mat-select>
    </mat-form-field>
    
    <!-- Switch Depending on the type -->
    <div [ngSwitch]="selectedRoomType">
    
      <!-- If type is roomsSimples -->
      <div *ngSwitchCase="'roomsSimples'">
        <strong> Rooms Simple Form </strong>
      </div>
    
      <!-- If type is roomsDoubles -->
      <div *ngSwitchCase="'roomsDoubles'">
        <strong> Rooms Doubles Form </strong>
      </div>
    
      <!-- Any other value (including undefined) -->
      <div *ngSwitchDefault>
        <strong> Select a Room Type </strong>
      </div>
    
    </div>
    

    Here is a working stackblitz https://stackblitz.com/edit/angular-ivy-6uwuux Please make sure to checkout angular docs https://angular.io/api/common/NgSwitch

    Also, I suggest using enums for your types, it would make it a lot easier to refactor your code in case your type values change in the future.