Cody
Cody

Reputation: 35

Why does the default value not render on Mat Select dropdown?

I'm fairly new to Angular, but unless I remove the ngModel from my Mat Select (which is used for my GraphQL mutation), it won't render the default value. My goal is to have the dropdown pre-filled with the user's current position.

<mat-list-item>
      <mat-form-field>
        <mat-label>Location</mat-label>
        <mat-select [value]="user.position" matNativeControl required [(ngModel)]="newLocation">
          <mat-option value="Top">Top</mat-option>
          <mat-option value="Front">Front</mat-option>
          <mat-option value="Middle">Middle</mat-option>
          <mat-option value="Back">Back</mat-option>
          <mat-option value="Right">Right</mat-option>
          <mat-option value="Left">Left</mat-option>
        </mat-select>
      </mat-form-field>
</mat-list-item>

Here is the TS file:

  updateUser(userId) {
    this.apollo
      .mutate({
        mutation: EDIT_USER,
        variables: {
          input: {
            userPosition: this.newLocation,
          }
        }
      })
      .subscribe(
        ({ data }) => {
          if (data['editUser'].complete) {
            this.getAssets();
            const user = this.assetDetails.users.find((s) => s.id === userId);
            user.userPosition = this.newLocation;
          }
        },
        (error) => {}
      );
  }

I have verified that user.position gives me the correct value, because it renders once [(ngModel)]="newLocation" is removed, but like I said earlier, is needed for my mutation. I can't seem to figure out a workaround. Appreciate any input.

Upvotes: 0

Views: 962

Answers (3)

Cody
Cody

Reputation: 35

I figured out with the help of the other answers:

I basically had to set the value in ngModel (newLocation) to a variable that held the initial value, before the mutation) rather than setting the new value to 'newLocation'. That way, it will render the initial / default value. I then passed that variable as a parameter to my mutation.

Here is a snippet of the updated code:

<mat-list-item>
      <mat-form-field>
        <mat-label>Location</mat-label>
        <mat-select [value]="user.position" matNativeControl required [(ngModel)]="user.userPosition">
          <mat-option value="Top">Top</mat-option>
          <mat-option value="Front">Front</mat-option>
          <mat-option value="Middle">Middle</mat-option>
          <mat-option value="Back">Back</mat-option>
          <mat-option value="Right">Right</mat-option>
          <mat-option value="Left">Left</mat-option>
        </mat-select>
      </mat-form-field>
</mat-list-item>

I then called my function like so:

updateUser(user.id, user.userPosition)

And the TS:

  updateUser(userId, position) {
    this.apollo
      .mutate({
        mutation: EDIT_USER,
        variables: {
          input: {
            userPosition: position,
          }
        }
      })
      .subscribe(
        ({ data }) => {
          if (data['editUser'].complete) {
            this.getAssets();
            const user = this.assetDetails.users.find((s) => s.id === userId);
            user.userPosition = position;
          }
        },
        (error) => {}
      );
  }

A really simple fix. ngModel and value can't be used simultaneously, as ngModel takes precedence.

Upvotes: 0

Abdalhadi Obaid
Abdalhadi Obaid

Reputation: 11

You should either use ngModel or Value, not both together.

Upvotes: 1

Anarno
Anarno

Reputation: 1640

Just remove the matNativeControl and the [(ngModel)] binding. After this, the predefined value will work (If the user.position value is equal any options value. This is case sensitive).

Upvotes: 1

Related Questions