bas
bas

Reputation: 14982

Angular show mat-select with enum options, and save the selected item

Trying to get through the maze of different (outdated?) options online to figure out to simply show a mat-select which is populated with the possible values of an enum, and store the result so that I can send the selected option to the back end.

Most options I've seen simply won't compile (anymore?). So I went with this, every bit of advise is more than welcome, I am obviously still very much learning angular...

In my dialog

        <div>
            <mat-label>Type</mat-label>

            <mat-select>
                <mat-option *ngFor="let type of getKeys() | keyvalue" [value]="type.key">
                    {{type.value}}
                </mat-option>
            </mat-select>
        </div>

In the dialog.ts

I copy&pasted

    getKeys() {
        const contactPersonMap = new Map<ContactPersonType, string> ([
        [ContactPersonType.Invoicing, 'Invoicing'],
        [ContactPersonType.SignWorkingHours, 'Sign month reports']
      ]);
      return contactPersonMap;
    }

A much cleaner approach seems (suggested by gpt):

const fruitMap = Object.keys(Fruit).reduce((map, key) => {
  map[Fruit[key]] = key;
  return map;
}, {});

But I get compile errors complaining about implicit any types I don't know how to resolve. So for now I will stick with the "more boiler plate" approach of defining the map by hand until I am a bigger boy.

In the dialog I also send back the "model" I passed in as follows:

    add() {
      this.dialogRef.close(this.data);
    }

Using the dialog

Then finally in the .ts where I open the dailog and await the result

      const dialogConfig = new MatDialogConfig();
      dialogConfig.data = this.selectedContactPerson;

      const dialogRef = this.dialog.open(AddCustomerContactDialog, dialogConfig);
  
      dialogRef.afterClosed().subscribe(result => {
        
        console.log(`${result.firstName}`);
        console.log(`${result.lastName}`);
        console.log(`${result.type}`);
      });

The firstName, lastName (which are simple matInput with an ngModel behind it) work. Yey for me.

But logging the type, it prints 'undefined'.

Help :)

How do I get this working? I want to the dialog to set the selected enum value in the model.

Side question

I forgot to mention, I started by defining the <mat-option> as follows

<mat-option *ngFor="let type of getKeys() | keyvalue" [(ngModel)]="type.key" #type="ngModel" name="type">

The select gets populated then, but when I select a value, the selected item remains empty. If somebody is willing to explain why that is, would be appreciated too.

PS: besides being new to Angular, I know close to nothing about javascript which I am sure doesn't help me. So apologies if this is a horrible question, but I am trying to get this to work for days in my lost hours getting nowhere.

Upvotes: 1

Views: 1893

Answers (2)

jaredlee.dev
jaredlee.dev

Reputation: 45

Here is one way:

// Wherever the enum is defined
enum SomeOptions {
    Option1 = 0, // Or some other value
    Option2 = 1,
}

// In your template
<mat-form-field>
    <mat-label>Options</mat-label>
    <mat-select>
      <mat-option *ngFor="let option of SomeOptions.values()" [value]="option">
        {{ SomeOptions[option] }}
      </mat-option>
    </mat-select>
  </mat-form-field>

The mat-select would then have the options of "Option1" and "Option2" shown to the user, and the selected option value would be 0 and 1 respectively.

Upvotes: 0

Wandrille
Wandrille

Reputation: 6821

If you are allowed to have any, you can still do:

types =  Object.keys(FRUIT).map(
    (fruit) => ({ key: fruit, value: (FRUIT as any)[fruit] })
  );

and

<mat-option *ngFor="let type of types" [value]="type.key">
       {{type.value}}
</mat-option>

Upvotes: 0

Related Questions