Home > Software design >  Can't set mat-selects default value
Can't set mat-selects default value

Time:03-11

I am doing edit page, so i am using patchValue for my form to set default value. in json it stores right data, but mat-selects default value isn't setting. what am i doing wrong?

i tried setting it with "[value]="item.name"" it works, but i need whole value for sending API request not only name.

my stackblitz

.html

<mat-select #multiSelect formControlName="carPartCategory" [value]="filterForm.value.carPartCategory"
            (selectionChange)="onChange($event); getCarPartsSubCategory($event)">
            <mat-option>
            <ngx-mat-select-search [formControl]="carPartsMultiFilterCtrl" [placeholderLabel]="'search...'"
              [noEntriesFoundLabel]="'not found'">
            </ngx-mat-select-search>
          </mat-option>
            <mat-option *ngFor="let item of filteredcarParts | async" [value]="item">{{item.name}}
            </mat-option>
          </mat-select>

          <mat-select #multiSelect formControlName="carPartSubCategory" [value]="filterForm.value.carPartSubCategory">
          <mat-option>
          <ngx-mat-select-search [formControl]="carPartsSubMultiFilterCtrl"
            [placeholderLabel]="'search...'" [noEntriesFoundLabel]="'not found'">>
          </ngx-mat-select-search>
        </mat-option>
            <mat-option *ngFor="let item of filteredcarPartsSub | async; let i = index;" [value]="item">
              {{item.name}}
            </mat-option>
          </mat-select>

.ts

 patchValues(name, carPartSubCategoryId, quantity, comment) {
    return this.fb.group({
      carPartCategory: [name],
      carPartSubCategory: [carPartSubCategoryId],
      quantity: [quantity],
      comment: [comment],
    });
  }

    const control = <FormArray>this.filterForm.get('categories');
    this.chosenCarPartCategories.carPartCategories.forEach((x) => {
      control.push(
        this.patchValues(x.name, x.carPartSubCategoryId, x.quantity, x.comment)
      );
    });

CodePudding user response:

There are a few bugs in your code preventing it from working.

Here is a working stackblitz: https://stackblitz.com/edit/angular-ivy-2zdvpu

The main problems are described bellow:

  1. You must use the compareWith function on the mat-select-input in order to change its value using patchValue, as described here Angular patchValue of a mat-select component

HTML:

<mat-select
    [compareWith]="compareFnSubcategories"
    #multiSelect
    formControlName="carPartSubCategory"
    [value]="filterForm.value.carPartSubCategory"
>

Typescript:

  compareFnSubcategories(c1: { carPartSubCategoryId: string }, 
                         c2: { carPartSubCategoryId: string }): boolean {
    return c1.carPartSubCategoryId === c2.carPartSubCategoryId;
  }
  1. You are calling patchValue only once and after the component is loaded. What you should be doing instead is invoking patchValue whenever there is a change in the category select, in order to update the child controls:

Typescript:

  //This is the function invoked when the category select changes.
  //It is here where you should invoke patchValue
  getCarPartsSubCategory(event: any, index: number) {
    const control = <FormArray>this.filterForm.get('categories');
    const selectedCategory = this.chosenCarPartCategories.carPartCategories
      .find(cp => cp.carPartCategoryId === event.value.carPartCategoryId);

    control.controls[index].patchValue({
      carPartSubCategory: selectedCategory,
      quantity: selectedCategory.quantity,
      comment: selectedCategory.comment,
    });
  }
  1. As you have a formArray of categories, the patchValue must be called only in the controls of the array index where the on change event happened. So you have to use the array index as a param to the function handling on change events:

See bellow how the index i of the formArray of categories is supplied as argument to the getCarPartsSubCategory(...) function.

HTML:

<div
      
      *ngFor="let obj of formArrCat.controls; let i = index; let l = last"
      [formGroupName]="i"
    >
    
    
  <mat-select
    ...
    (selectionChange)="
      onChange($event); getCarPartsSubCategory($event, i)
    "
  >
  ...
  </mat-select>
  
</div>
  • Related