角材料选择-默认值-反应形式

时间:2020-02-04 04:07:57

标签: angular firebase angular-material

我在这里丢了。关于这个主题有很多问题,无论我怎么尝试,我都无法使它起作用。

我只是想设置Mat-select的默认值。

我有一个员工列表。单击列表项将打开一个对话框(“员工详细信息”),因此我可以编辑(或添加)员工的数据。我只希望部门编辑时选择该部门以显示员工的当前部门。

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>

,它看起来像(这告诉我Employee对象正好将其移到对话框中):

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

要使用填充选项填充部门,我使用的是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;
}

department.ts

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

2 个答案:

答案 0 :(得分:1)

原因是因为员工记录中的部门对象与查询结果中的部门对象不匹配。是的,值匹配,但是对象引用不匹配(它是一个单独的对象)。

您可以使用[compareWith]属性来传递比较对象ID的函数。 mat-select支持与标准Angular select相同的[compareWith]功能。 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;
}

答案 1 :(得分:0)

尝试

ngAfterViewInit() {
 this.form.controls['department'].setValue(this.data.employee.department);
}