Angular Выбор материала - Значение по умолчанию - Реактивные формы - PullRequest
0 голосов
/ 04 февраля 2020

Я теряю это здесь. Есть так много вопросов на эту тему, и независимо от того, что я пытаюсь, я не могу заставить его работать.

Я просто хочу установить значение по умолчанию выбора циновки.

У меня есть список сотрудников. При нажатии на элемент списка открывается диалоговое окно (Сведения о сотруднике), чтобы я мог редактировать (или добавлять) данные сотрудника. Я просто хочу, чтобы функция выбора коврика отображала текущий отдел сотрудника при редактировании режима.

employee-details.component. html

<div fxLayout="column">
   <div class="flex-item" fxFlex mat-dialog-actions fxLayoutAlign="end">
      <button mat-mini-fab color="" aria-label="Cancel" (click)="onCancelClick()">
         <mat-icon>clear</mat-icon>
      </button>
   </div>
   <h4 *ngIf="data.action == 'add'">Add New Employee</h4>
   <h4 *ngIf="data.action == 'edit'">Edit Employee</h4>
   <form [formGroup]="form" class="employee-form">
      <div class="form-group">
         <mat-form-field class="employee-full-width">
            <input
               formControlName="firstname"
               matInput
               required
               placeholder="Employee Firstname"
               >
            <mat-error
               *ngIf="
               form.get('firstname').touched && form.get('firstname').invalid
               "
               >Employee Firstname is Required!</mat-error
               >
         </mat-form-field>
         <mat-form-field class="employee-full-width">
            <input
               formControlName="lastname"
               matInput
               required
               placeholder="Employee Lastname"
               >
            <mat-error
               *ngIf="
               form.get('lastname').touched && form.get('lastname').invalid
               "
               >Employee Lastname is Required!</mat-error
               >
         </mat-form-field>
         <mat-form-field class="employee-full-width">
            <input
               formControlName="title"
               matInput
               required
               placeholder="Employee Title"
               >
            <mat-error
               *ngIf="
               form.get('title').touched && form.get('title').invalid
               "
               >Employee Title is Required!</mat-error
               >
         </mat-form-field>
         <mat-form-field class="employee-full-width">
            <input
               formControlName="rate"
               matInput
               required
               placeholder="Employee Rate"
               >
            <mat-error
               *ngIf="
               form.get('rate').touched && form.get('rate').invalid
               "
               >Employee Rate is Required!</mat-error
               >
         </mat-form-field>
         <mat-form-field class="employee-full-width">
            <mat-label>Department</mat-label>
            <mat-select formControlName="department">
               <mat-option *ngFor="let dept of departments" [value]="dept">
               {{ dept?.title }}
               </mat-option>
            </mat-select>
         </mat-form-field>
      </div>
   </form>
   <div class="flex-item" fxFlex mat-dialog-actions fxLayoutAlign="end">
      <button
         mat-raised-button
         color="secondary"
         class="project-add-button"
         (click)="onNoClick()"
         >
      Cancel
      </button>
      <button
      mat-raised-button
      [disabled]="!form.valid"
      color="primary"
      class="project-add-button"
      (click)="createEmployee(form)"
      >
      Save & Close
      </button>
      <button
      mat-raised-button
      [disabled]="!form.valid"
      color="primary"
      class="project-add-button"
      (click)="createEmployee(form)"
      >
      Save & New
      </button>
   </div>
</div>
<div>
   <div>
      <br />
      <br />
      <mat-accordion>
         <mat-expansion-panel>
            <mat-expansion-panel-header>
               <mat-panel-title>
                  Form value
               </mat-panel-title>
            </mat-expansion-panel-header>
            <code>
               <div fxLayout="column" fxLayoutGap="32px">
                  <div>{{ form.value | json }}</div>
                  <div>Form Validity: {{ form.valid | json}}</div>
               </div>
            </code>
         </mat-expansion-panel>
      </mat-accordion>
   </div>
</div>

employee-details.component.ts

import { Component, OnInit, Optional, Inject, AfterViewInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { EmployeeService } from 'src/app/core/services/entity/employee.service';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
import { DialogData } from 'src/app/employees/employee-list/employee-list.component';
import { DepartmentService } from 'src/app/core/services/entity/department.service';
import { Department } from 'src/app/shared/models/department';

@Component({
  selector: 'app-employee-details',
  templateUrl: './employee-details.component.html',
  styleUrls: ['./employee-details.component.css']
})
export class EmployeeDetailsComponent implements OnInit, AfterViewInit {
  departments: Department[];
  selectedDepartment: Department;

  form = new FormGroup({
    id: new FormControl(''),
    firstname: new FormControl(''),
    lastname: new FormControl(''),
    title: new FormControl(''),
    rate: new FormControl(''),
    department: new FormControl(''),
  });

  constructor(
    private departmentService: DepartmentService,
    private service: EmployeeService,
    public dialogRef: MatDialogRef<EmployeeDetailsComponent>,
    @Optional() @Inject(MAT_DIALOG_DATA) public data: DialogData
  ) {
    if (data.action === 'edit') {
      this.form.patchValue(data.employee);
    }
  }

  ngOnInit() {
    this.departmentService.departments$.subscribe(r => {
      this.departments = r;
    });
  }
  // **** THIS DOESN'T ACTUALLY DO ANYTHING, AS FAR AS I CAN TELL ****
  ngAfterViewInit() {
    this.form.controls.department.setValue(this.data.employee.department);
  }

  createEmployee(f: FormGroup) {
    if (this.data.action === 'edit') {
      this.service.updateEmployee(f.value).then(response => {
        this.closeDialog();
      });
      // creating a new one
    } else {
      this.service.createEmployee(f.value).then(response => {
        this.closeDialog();
      });
    }
  }

  onCancelClick() {
    this.onNoClick();
  }

  onNoClick() {
    this.dialogRef.close({
      event: 'cancel'
    });
  }

  closeDialog() {
    this.dialogRef.close({
      event: this.data.action,
      data: this.data.employee
    });
  }
}

Я отображаю «данные» в нижней части диалогового окна, используя:

<div>{{ form.value | json }}</div>

, и это выглядит like (что говорит мне, что объект Employee перенаправляет его в диалоговое окно просто отлично):

{
    "id": "9UAPoKCFofH7aWBUwdiO",
    "firstname": "John",
    "lastname": "Doe",
    "title": "Manager",
    "rate": "120",
    "department": {
        "code": "1000",
        "id": "2PtDUwPBXT7pUPWTOibD",
        "title": "Project Management"
    }
}

Чтобы заполнить mat-select отделов, я использую сервис, который CRUDs Firebase:

  ngOnInit() {
    this.departmentService.departments$.subscribe(r => {
      this.departments = r;
    });
  }

Соответствующий HTML из шаблона:

<mat-form-field class="employee-full-width">
  <mat-label>Department</mat-label>
    <mat-select formControlName="department">
      <mat-option *ngFor="let dept of departments" [value]="dept">
       {{ dept?.title }}
      </mat-option>
    </mat-select>
</mat-form-field>

employee.ts

import { Department } from './department';

export interface Employee {
    id: string;
    firstname: string;
    lastname: string;
    title: string;
    department: Department;
    rate: number;
}

отдел.ц

export interface Department {
    id: string;
    title: string;
    code: string;
}

Ответы [ 2 ]

1 голос
/ 04 февраля 2020

Причина в том, что объект отдела в вашей записи сотрудника не соответствует объекту отдела в результате запроса. Да, значения совпадают, но ссылка на объект не совпадает (это отдельный объект).

Вы можете использовать атрибут [compareWith] для передачи функции, которая сравнивает идентификаторы объектов. mat-select поддерживает те же функциональные возможности [compareWith], что и стандартный Angular select. https://angular.io/api/forms/SelectControlValueAccessor#customizing -option-selection

Таким образом, у вас будет это в вашем шаблоне:

<mat-select formControlName="department" [compareWith]="compareFn">

А затем в вашем компоненте:

compareFn(d1: Department, d2: Department): boolean {
    return d1 && d2 ? d1.id === d2.id : d1 === d2;
}
0 голосов
/ 04 февраля 2020

Попробуйте

ngAfterViewInit() {
 this.form.controls['department'].setValue(this.data.employee.department);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...