1
votes

I'm struggling getting the default selected option working and changing it based on a button click in my Angular 8 (Material) application.

I have created a stackblitz to demonstrate the same.

https://stackblitz.com/edit/angular-hbocgp

I want the region drop down to have default options selected as "North America" and on click of the button i want it to set it to some other options.

app.component.html

<mat-card>
      <mat-form-field>
        <mat-label>Region</mat-label>
        <mat-select [(ngModel)]="regionSelected">
          <mat-option *ngFor="let row of regionSelectionList" [value]="row">
            {{row.name}}
          </mat-option>
        </mat-select>
      </mat-form-field>

      <button mat-raised-button color="primary" (click)="setRegion()">Set Region</button>
</mat-card>

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  regionSelected = { "itemId": 1, "name": "North America Seed" };
  regionSelectionList = [
    {"itemId":1, "name":"North America Seed"},
    {"itemId":67505, "name":"1B:  CU2 (North and Far West)"},
    {"itemId":67504, "name":"1C:  CU1 (Western Cornbelt)"},
    {"itemId":67506, "name":"1K:  CU3 (Eastern Cornbelt)"},
    {"itemId":67503, "name":"1U:  CU4 (Southern)"},
    {"itemId":65143, "name":"5A:  CU5 (Canada)"}
    ];

    setRegion(){
      console.log("Clicked");
      this.regionSelected = {"itemId":67505, "name":"1B:  CU2 (North and Far West)"};
    }
}

Update:

Thanks for all the answers, but i ended up using below:

//default

this.regionSelected = this.regionSelectionList[this.regionSelectionList.findIndex(lst => lst.itemId == 1)];

// On button click

this.regionSelected = this.regionSelectionList[this.regionSelectionList.findIndex(lst => lst.itemId == 67505)];
3

3 Answers

1
votes

The problem is referential equality. Even though in your sample code you're using all the same data, you're still creating different objects.

This happens because in your template you bind [value]="row", where row is an object. If you'd bind to row.itemId instead, and have regionSelected equal to 1 from the start, and instead of assigning an object in the setRegion() function, assign a necessary itemId - it would work.

Like this:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  name = 'Angular';
  regionSelectionList = [
    {"itemId":1, "name":"North America Seed"},
    {"itemId":67505, "name":"1B:  CU2 (North and Far West)"},
    {"itemId":67504, "name":"1C:  CU1 (Western Cornbelt)"},
    {"itemId":67506, "name":"1K:  CU3 (Eastern Cornbelt)"},
    {"itemId":67503, "name":"1U:  CU4 (Southern)"},
    {"itemId":65143, "name":"5A:  CU5 (Canada)"}
  ];
  regionSelected = 1;


  setRegion(){
    console.log("Clicked");
    this.regionSelected = 67505;
  }
}

OR, you could just use the same objects that's in your regionSelectionList and let Angular compare them by reference:

export class AppComponent  {
  name = 'Angular';
  regionSelectionList = [
    {"itemId":1, "name":"North America Seed"},
    {"itemId":67505, "name":"1B:  CU2 (North and Far West)"},
    {"itemId":67504, "name":"1C:  CU1 (Western Cornbelt)"},
    {"itemId":67506, "name":"1K:  CU3 (Eastern Cornbelt)"},
    {"itemId":67503, "name":"1U:  CU4 (Southern)"},
    {"itemId":65143, "name":"5A:  CU5 (Canada)"}
  ];
  regionSelected = this.regionSelectionList[0];


  setRegion(){
    console.log("Clicked");
    this.regionSelected = this.regionSelectionList[2];
  }
}
1
votes

Anser by @SudarshanaDayananda is actually correct, but just did not finish up, here is the working Stackblitz: https://angular-byx9ux.stackblitz.io

Why does your way not work? Your instantiation of

regionSelected = { "itemId": 1, "name": "North America Seed" };

might have the same variables, it is ,however, a different object compared to the one you have in your Array. In the select you are setting the objects in the array, therefore the the set model will not be matched to your select options.

Another possibility might be to set your own compare function:

HTML:

<select [compareWith]="compareFn" ..>

TS:

compareFn(item1: any, item2: any) {
    return item1 && item2 && item1.itemId === item2.itemId;
}
1
votes

Try as follows.

  regionSelected: any;

  constructor() {
    this.regionSelected = this.regionSelectionList[0];
  }

Update

If you want to set the second region to select on button click you can do it as below.

setRegion(){
  this.regionSelected = this.regionSelectionList[1];
}

StackBlitz