PeteBaser
PeteBaser

Reputation: 313

Angular Material: mat-select set value data from service using reactive forms

I have been struggling with this issue for a couple of days now, I hope somebody can help me with this.

I have a service which retrieves user from my back end. The user model looks like this:

declare interface IUser {
  id?: string;
  name?: string;
  email?: string;
  firebaseID?: string;
  firebaseEmail?: string;
  role?: string;
  phoneNumber?: string;
}

and I have a service which retrieves work orders from my back end.

In my work order form I want to show a list of user and the user who is already assigned to that work order (default value). The form is a reactive form (create-work-order-dialog) where I want to show the user selected the work order or show a list to select a different user to the work item.

My form with the users formControl is ( Monteur):

<div #container>
  <form
    [formGroup]="form"
    (ngSubmit)="save()"
    data-test="createFollowUpDialog"
    autocomplete="off"
  >
    <h1 mat-dialog-title>Maak een nieuwe werkorder aan</h1>
    <mat-dialog-content>
      <div class="row mt-3">
        <div class="col-md-12">
          <h2>Werkorder informatie</h2>
          <mat-form-field class="input">
            <mat-label>Omschrijving van het probleem</mat-label>
            <input
              formControlName="leakageReason"
              tabindex="1"
              autocomplete="off"
              matInput
              placeholder="Omschrijving van probleem"
              matTooltip="Omschrijving van het probleem"
            />
            <mat-error
              *ngIf="form.controls['leakageReason'].hasError('required')"
              >Verplicht
            </mat-error>
          </mat-form-field>
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-form-field class="input">
            <mat-label>Projectnummer</mat-label>
            <input
              formControlName="projectNumber"
              tabindex="2"
              autocomplete="off"
              matInput
              placeholder="Projectnummer"
            />
            <mat-error
              *ngIf="form.controls['projectNumber'].hasError('required')"
              >Verplicht
            </mat-error>
          </mat-form-field>
        </div>
      </div>
      <div formGroupName="client">
        <h3>Gegevens van de opdrachtgever</h3>
        <div class="row mt-3">
          <div class="col-md-12">
            <mat-form-field class="input">
              <mat-label>Naam opdrachtgever</mat-label>
              <input
                formControlName="name"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Naam van de opdrachtgever"
                placeholder="Naam opdrachtgever"
              />
              <mat-error *ngIf="form.get('client.name')?.hasError('required')"
                >Verplicht
              </mat-error>
            </mat-form-field>
          </div>
        </div>
        <div class="row mt-3">
          <div class="col-md-12">
            <mat-form-field class="input">
              <mat-label>Telnr. van opdrachtgever</mat-label>
              <input
                formControlName="phoneNumber"
                tabindex="2"
                autocomplete="off"
                matInput
                required
                matTooltip="Telnr. van de opdrachtgever"
                placeholder="Telnr. opdrachtgever"
              />
              <mat-error
                *ngIf="form.get('client.phoneNumber')?.hasError('required')"
                >Verplicht
              </mat-error>
            </mat-form-field>
          </div>
        </div>
        <div class="row mt-3">
          <div class="col-md-12">
            <mat-form-field class="input">
              <mat-label>Mobielnr. van opdrachtgever</mat-label>
              <input
                formControlName="mobilePhoneNumber"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Mobielnr. van de opdrachtgever"
                placeholder="Mobielnr. opdrachtgever"
              />
            </mat-form-field>
          </div>
        </div>
      </div>
      <div formGroupName="customer">
        <h3>Gegevens van de klant</h3>
        <div class="row mt-3">
          <div class="col-md-12">
            <mat-form-field class="input">
              <mat-label>Naam Klant</mat-label>
              <input
                formControlName="name"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Naam van de klant"
                placeholder="Naam klant"
              />
              <mat-error *ngIf="form.get('customer.name')?.hasError('required')"
                >Verplicht
              </mat-error>
            </mat-form-field>
          </div>
        </div>
        <div class="row mt-3">
          <div class="col-md-8">
            <mat-form-field class="input">
              <mat-label>Adres van klant</mat-label>
              <input
                formControlName="street"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Straat van de klant"
                placeholder="straat klant"
              />
              <mat-error
                *ngIf="form.get('customer.street')?.hasError('required')"
                >Verplicht
              </mat-error>
            </mat-form-field>
          </div>
          <div class="col-md-2">
            <mat-form-field class="input addressWidth">
              <mat-label>Huisnr.</mat-label>
              <input
                formControlName="houseNumber"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Huisnummer"
                placeholder="Huisnr."
              />
              <mat-error
                *ngIf="form.get('customer.houseNumber')?.hasError('required')"
                >Verplicht
              </mat-error>
            </mat-form-field>
          </div>
          <div class="col-md-2">
            <mat-form-field class="input addressWidth">
              <mat-label>toevoeging</mat-label>
              <input
                formControlName="houseNumberExt"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Huisnummer toevoeging"
                placeholder="toevoeging"
              />
            </mat-form-field>
          </div>
        </div>
        <div class="row mt-3">
          <div class="col-md-4">
            <mat-form-field class="input zipCodeWidth">
              <mat-label>Postcode</mat-label>
              <input
                formControlName="zipCode"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Postcode"
                placeholder="Postcode"
              />
              <mat-error
                *ngIf="form.get('customer.zipCode')?.hasError('required')"
                >Verplicht
              </mat-error>
            </mat-form-field>
          </div>
          <div class="col-md-4">
            <mat-form-field class="input">
              <mat-label>Plaats</mat-label>
              <input
                formControlName="city"
                tabindex="2"
                autocomplete="off"
                matInput
                matTooltip="Plaats"
                placeholder="Plaats"
              />
              <mat-error *ngIf="form.get('customer.city')?.hasError('required')"
                >Verplicht
              </mat-error>
            </mat-form-field>
          </div>
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-form-field class="datepicker">
            <mat-label>Inspectiedatum </mat-label>
            <input
              matInput
              formControlName="dateInspection"
              tabindex="3"
              [matDatepicker]="pickerIn"
            />
            <mat-datepicker-toggle
              tabindex="-1"
              matSuffix
              [for]="pickerIn"
            ></mat-datepicker-toggle>
            <mat-datepicker #pickerIn></mat-datepicker>
          </mat-form-field>
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-form-field class="input">
            <mat-label>Status werkorder</mat-label>
            <mat-select formControlName="status" name="status" tabindex="4">
              <mat-option
                *ngFor="let status of statusWerkOrder"
                [value]="status"
              >
                {{ status }}
              </mat-option>
            </mat-select></mat-form-field
          >
        </div>
      </div>
      <div formGroupName="user" class="mt-4 mb-3">
        <div class="row mt-3">
          <div class="col-md-12">
            <mat-form-field class="input">
              <mat-label>Monteur</mat-label>
              <mat-select
                formControlName="name"
                name="name"
                tabindex="5"
                [(value)]="data.user.name"
              >
                <mat-option
                  *ngFor="let mechanic of mechanics"
                  [value]="mechanic"
                >
                  {{ mechanic.name }}
                </mat-option>
              </mat-select>
            </mat-form-field>
          </div>
        </div>
      </div>
      <pre>{{ data.user.name }}</pre>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-slide-toggle
            color="primary"
            formControlName="followupInspection"
            tabindex="5"
            >Opvolgmelding?</mat-slide-toggle
          >
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-slide-toggle
            color="primary"
            formControlName="clientPresent"
            tabindex="6"
            >Is de klant aanwezig?</mat-slide-toggle
          >
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-slide-toggle
            color="primary"
            formControlName="visibleWaterDamage"
            tabindex="7"
            >Zichtbare waterschade?</mat-slide-toggle
          >
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-form-field class="input">
            <mat-label>Duur waterschade</mat-label>
            <input
              formControlName="visibleWaterDamagePeriod"
              tabindex="8"
              autocomplete="off"
              matInput
              matTooltip="Duur waterschade (dag, week, etc.)"
              placeholder="Duur waterschade"
            />
          </mat-form-field>
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-form-field class="input">
            <mat-label>Soort gebouw</mat-label>
            <mat-select
              formControlName="buildingType"
              name="buildingType"
              tabindex="9"
            >
              <mat-option
                *ngFor="let buildingType of buildingTypes"
                [value]="buildingType"
              >
                {{ buildingType }}
              </mat-option>
            </mat-select></mat-form-field
          >
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-form-field class="input">
            <mat-label>Bouwjaar</mat-label>
            <input
              formControlName="buildingEstablished"
              tabindex="10"
              autocomplete="off"
              matInput
              placeholder="Bouwjaar"
              matTooltip="Bouwjaar van het object"
            />
          </mat-form-field>
        </div>
      </div>
      <div class="row mt-3">
        <div class="col-md-12">
          <mat-form-field class="input">
            <mat-label>Renovatie jaar</mat-label>
            <input
              formControlName="renovatedYear"
              tabindex="11"
              autocomplete="off"
              matInput
              placeholder="Renovatie jaar"
              matTooltip="Renovatie jaar van het object"
            />
          </mat-form-field>
        </div>
      </div>
    </mat-dialog-content>
    <mat-dialog-actions class="d-flex">
      <button
        mat-raised-button
        type="submit"
        color="primary"
        tabindex="29"
        class="align-items-end"
        [disabled]="!form.valid"
        matTooltip="Na opslaan worden de openstaande meldingen ververst zodat de melding direct ingepland kan worden"
      >
        Opslaan
      </button>
      <button
        mat-raised-button
        tabindex="30"
        [mat-dialog-close]="true"
        data-test="cancelCloseDialog"
        class="align-items-end"
      >
        Annuleren
      </button>
    </mat-dialog-actions>
  </form>
</div>

my ts file

import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import {
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from '@angular/forms';
import { WorkOrderService } from '../services/work-order.service';
import { takeUntil } from 'rxjs/operators';
import { Observable, Subject } from 'rxjs';
import { CustomSnackbarService } from '../../shared/services/custom-snackbar.service';
import { Router } from '@angular/router';
import { v4 as uuidv4 } from 'uuid';
import { UserService } from '../../shared/services/user.service';

@Component({
  selector: 'app-create-work-order-dialog',
  templateUrl: './create-work-order-dialog.component.html',
  styleUrls: ['./create-work-order-dialog.component.css'],
})
export class CreateWorkOrderDialogComponent implements OnInit, OnDestroy {
  form: FormGroup;
  data: IWorkOrder;
  alreadySetDescriptionUpdated = false;
  showEditDescription = false;
  isLoading = false;
  buildingTypes: string[] = [
    'Hoekwoning',
    'Appartement',
    'Woonhuis',
    'Vrijstaand',
  ];
  statusWerkOrder: string[] = ['Open', 'In behandeling', 'Gesloten'];
  panelOpenState = false;
  onDestroy$ = new Subject();
  mechanics: any;

  constructor(
    public dialogRef: MatDialogRef<CreateWorkOrderDialogComponent>,
    @Inject(MAT_DIALOG_DATA)
    public passedData: { workOrder: IWorkOrder; mechanics: IUser },
    private formBuilder: FormBuilder,
    private workOrderService: WorkOrderService,
    private customSnackbarService: CustomSnackbarService,
    private userService: UserService,
    private router: Router
  ) {}

  ngOnInit(): void {
    // this.getMechanics();
    console.log('####--passedData', this.passedData);
    this.mechanics = this.passedData.mechanics;
    this.data = this.passedData.workOrder;
    this.buildForm();
  }

  ngOnDestroy() {
    this.onDestroy$.next();
    this.onDestroy$.complete();
  }

  private getMechanics() {
    this.userService
      .getUsers()
      .pipe(takeUntil(this.onDestroy$))
      .subscribe((users: IUser[]) => {
        this.mechanics = users.filter(
          (user: IUser) => user.role === 'technician'
        );
      });
  }

  save() {
    this.isLoading = true;
    const workOrder: IWorkOrder = { ...this.data, ...this.form.value };

    if (this.data && this.data !== null && this.data !== undefined) {
      this.workOrderService
        .updateWorkOrderForPlanning(workOrder)
        .pipe(takeUntil(this.onDestroy$))
        .subscribe(
          (data: IWorkOrder) => {
            this.isLoading = false;
            this.customSnackbarService.notification$.next({
              message: `Werkorder is ge-update`,
              type: 'info',
            });
            this.dialogRef.close();
            this.router.navigate(['planning']);
            this.workOrderService.refreshWorkOrders.next(true);
          },
          (error: any) => {
            this.customSnackbarService.notification$.next({
              message: `Fout bij aanmaken van werkorder: ${error}`,
              type: 'error',
            });
            console.log('Create Follow-up failure', error);
            this.isLoading = false;
          }
        );
    } else {
      this.workOrderService
        .createWorkOrderForPlanning(workOrder)
        .pipe(takeUntil(this.onDestroy$))
        .subscribe(
          (data: IWorkOrder) => {
            this.isLoading = false;
            this.customSnackbarService.notification$.next({
              message: `Werkorder is aangemaakt`,
              type: 'info',
            });
            this.dialogRef.close();
            this.workOrderService.refreshWorkOrders.next(true);
            this.router.navigate(['planning']);
          },
          (error: any) => {
            this.customSnackbarService.notification$.next({
              message: `Fout bij aanmaken van werkorder: ${error}`,
              type: 'error',
            });
            console.log('Create Follow-up failure', error);
            this.isLoading = false;
          }
        );
    }
  }

  private buildForm() {

    console.log('####--the data', this.data);
    this.form = this.formBuilder.group({
      id: [this.data?.id ? this.data.id : uuidv4()],
      projectNumber: new FormControl(this.data?.projectNumber, [
        Validators.required,
      ]),
      leakageReason: new FormControl(this.data?.leakageReason, [
        Validators.required,
      ]),
      dateInspection: new FormControl(this.data?.dateInspection, []),
      followupInspection: new FormControl(this.data?.followupInspection, []),
      clientPresent: new FormControl(this.data?.clientPresent, []),
      visibleWaterDamage: new FormControl(this.data?.visibleWaterDamage, []),
      visibleWaterDamagePeriod: new FormControl(
        this.data?.visibleWaterDamagePeriod,
        []
      ),
      buildingType: new FormControl(this.data?.buildingType, []),
      renovatedYear: new FormControl(this.data?.renovatedYear, []),
      buildingEstablished: new FormControl(this.data?.buildingEstablished, []),
      status: new FormControl(this.data?.status, []),
      user: this.formBuilder.group({
        id: [this.data?.user?.id],
        name: new FormControl(this.data?.user?.name),
        email: new FormControl(this.data?.user?.email),
        firebaseID: new FormControl(this.data?.user?.firebaseID),
        firebaseEmail: new FormControl(this.data?.user?.firebaseEmail),
        role: new FormControl(this.data?.user?.role),
        phoneNumber: new FormControl(this.data?.user?.phoneNumber),
      }),
      client: this.formBuilder.group({
        id: [this.data?.client?.id ? this.data.client.id : uuidv4()],
        name: new FormControl(this.data?.client?.name),
        contactPerson: new FormControl(this.data?.client?.contactPerson),
        email: new FormControl(this.data?.client?.email),
        phoneNumber: new FormControl(this.data?.client?.phoneNumber),
        mobilePhoneNumber: new FormControl(
          this.data?.client?.mobilePhoneNumber
        ),
        street: new FormControl(this.data?.client?.street),
        houseNumber: new FormControl(this.data?.client?.houseNumber),
        houseNumberExt: new FormControl(this.data?.client?.houseNumberExt),
        zipCode: new FormControl(this.data?.client?.zipCode),
        city: new FormControl(this.data?.client?.city),
        attribute: new FormControl(this.data?.client?.attribute),
      }),
      customer: this.formBuilder.group({
        id: [this.data?.customer?.id ? this.data.customer.id : uuidv4()],
        name: new FormControl(this.data?.customer?.name, [Validators.required]),
        contactPerson: new FormControl(this.data?.customer?.contactPerson),
        street: new FormControl(this.data?.customer?.street, [
          Validators.required,
        ]),
        houseNumber: new FormControl(this.data?.customer?.houseNumber, [
          Validators.required,
        ]),
        houseNumberExt: new FormControl(this.data?.customer?.houseNumberExt),
        zipCode: new FormControl(this.data?.customer?.zipCode, [
          Validators.required,
        ]),
        city: new FormControl(this.data?.customer?.city, [Validators.required]),
        phoneNumber: new FormControl(this.data?.customer?.phoneNumber, []),
        mobilePhoneNumber: new FormControl(
          this.data?.customer?.mobilePhoneNumber,
          []
        ),
      }),
      expertiseOffice: this.formBuilder.group({
        id: [
          this.data?.expertiseOffice?.id
            ? this.data.expertiseOffice.id
            : uuidv4(),
        ],
        expertiseOfficeName: new FormControl(this.data?.expertiseOffice?.name),
        fileNumber: new FormControl(this.data?.expertiseOffice?.fileNumber),
        nameOfAgent: new FormControl(this.data?.expertiseOffice?.nameOfAgent),
        phoneNumberAgent: new FormControl(
          this.data?.expertiseOffice?.phoneNumberAgent
        ),
        emailAgent: new FormControl(this.data?.expertiseOffice?.emailAgent),
        insuranceCompanyName: new FormControl(this.data?.expertiseOffice?.id),
        damageNumber: new FormControl(this.data?.expertiseOffice?.damageNumber),
        policyNumber: new FormControl(this.data?.expertiseOffice?.policyNumber),
      }),
    });
  }
}

The list of users (mechanics) is shown correctly but the user already assign to the work order does not show with his name in the "monteur" field.

How can I show the default value of the user (mechanic) who is already assigned to this workOrder?

Many many thanks for your help Pete

Upvotes: 1

Views: 1665

Answers (1)

Minal Shah
Minal Shah

Reputation: 1486

I think you are just giving the value in the wrong way, You have to provide the whole object in the list, providing only name would not work. And you need to write multiple if you want to make your dropdown multi select

please replace your code in html using the following lines:

<div class="col-md-12">
        <mat-form-field class="input">
          <mat-label>Monteur</mat-label>
          <mat-select
            formControlName="name"
            name="name"
            tabindex="5" multiple
            [value]="data.user"
          >
            <mat-option
              *ngFor="let mechanic of mechanics"
              [value]="mechanic"
            >
              {{ mechanic.name }}
            </mat-option>
          </mat-select>
        </mat-form-field>
      </div>

Upvotes: 2

Related Questions