繁体   English   中英

Angular材料中Dialog组件和父组件中的数据映射

[英]Data Maping in Dialog component and parent component in Angular material

我正在使用 angular 材质对话框来更新配置文件信息。 我正在使用相同的对话框进行添加/编辑。 我有一个 object '患者信息' ,其中包含患者详细信息以及另一个 object ,它提供了个人资料图像的信息。 我在对话框中的图像上给出了一个删除图像按钮。 我已将数据从父组件发送到子组件。 删除图像后,我将 object 设置为 null。 我观察到的是,当我更改子组件上的数据字段时,我的父组件数据也会更改。 谁能让我知道为什么会这样?

父级html

<!-- <section class="content-header">
  <div class="container-fluid">
    <h1>Patient Listing</h1>
  </div>
</section> -->

<mat-form-field>
  <mat-label>Search</mat-label>
  <input matInput (keyup)="applyFilter($event)" placeholder="Ex. Anything" #input>
</mat-form-field>

<button class="float-right add-patient-btn" mat-raised-button color="primary" (click)="onPatientEdit()">Add Patient</button>

<div class="mat-elevation-z8">
  <table mat-table [dataSource]="patientInformation" matSort>

    <ng-container matColumnDef="firstName">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> First Name </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.firstName}} </td>
    </ng-container>

    <ng-container matColumnDef="lastName">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Last Name </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.lastName}} </td> 
    </ng-container>

    <ng-container matColumnDef="email">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Email </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.email | emptyString}} </td>
    </ng-container>

    <ng-container matColumnDef="age">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Age </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.age}} </td>
    </ng-container>

    <ng-container matColumnDef="phone">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Phone </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.phone}} </td>
    </ng-container>

    <ng-container matColumnDef="gender">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Gender </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.gender | genderToString}} </td>
    </ng-container>

    <ng-container matColumnDef="history">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> History </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.history | emptyString}} </td>
    </ng-container>

    <ng-container matColumnDef="caseNo">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Case No </th>
      <td mat-cell *matCellDef="let patient" (click)="OnRowClick(patient)"> {{patient.caseNo | emptyString}} </td>
    </ng-container>

    <ng-container matColumnDef="patientActions">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Patient Actions </th>
      <td mat-cell *matCellDef="let patient">
        <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Example icon-button with a menu">
          <mat-icon>more_vert</mat-icon>
        </button>
        <mat-menu #menu="matMenu">
          <button mat-menu-item (click)="onPatientEdit(patient)">
            <mat-icon>edit</mat-icon>
            <span>Edit Patient</span>
          </button>
          <button mat-menu-item (click)="onPatientDelete(patient.id)">
            <mat-icon>delete</mat-icon>
            <span>Delete Patient</span>
          </button>
          <button mat-menu-item (click)="onPatientDetails(patient.id)">
            <mat-icon>details</mat-icon>
            <span>Patient Details</span>
          </button>
        </mat-menu>
        
      </td>
    </ng-container>
    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr class="element-row" mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
    <tr class="mat-row" *matNoDataRow>
      <td class="mat-cell" colspan="4">No data</td>
    </tr>
  </table>
  <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" [pageSize]=10></mat-paginator>
</div>

父级

import { Component, OnInit, ViewChild } from '@angular/core';
import { GetPatientInformationModel } from 'src/app/models/patient/GetPatientInformationModel';
import { PatientService } from '../patient.service';

import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { MatPaginator } from '@angular/material/paginator';
import { MatDialog } from '@angular/material/dialog';
import { LoadingService } from 'src/app/shared/loading.service';
import { Router } from '@angular/router';
import { EditPatientComponent } from '../edit-patient/edit-patient.component';
import { GuidModel } from 'src/app/models/common/GuidModel';
import { FileInformationModel } from 'src/app/models/common/FileInformationModel';
import { ConfirmDialogComponent } from '../../shared/components/confirm-dialog/confirm-dialog.component';
import { ToasterService } from '../../shared/toaster.service';

@Component({
  selector: 'app-patient-list',
  templateUrl: './patient-list.component.html',
  styleUrls: ['./patient-list.component.scss']
})
export class PatientListComponent implements OnInit {

  public patientPhotoInformation: FileInformationModel;
  public patientData: GetPatientInformationModel;

  public patientInformation: MatTableDataSource<GetPatientInformationModel>;
  displayedColumns: string[] = ['firstName', 'lastName', 'email', 'age', 'phone', 'gender', 'history', 'caseNo', 'patientActions'];
  @ViewChild(MatSort) sort: MatSort;
  @ViewChild(MatPaginator) paginator: MatPaginator;

  constructor(private patientService: PatientService,
    public dialog: MatDialog,
    private loading: LoadingService,
    private router: Router,
    private toasterService: ToasterService) { }

  ngOnInit(): void {
    this.loadNext();
  }

  initData() {
    this.patientPhotoInformation = {
      id: new GuidModel().Empty,
      name: null,
      size: null,
      creationDate: null,
      path: null,
      type: null
    }

    this.patientData = {
      id: new GuidModel().Empty,
      firstName: null,
      lastName: null,
      email: null,
      age: null,
      gender: null,
      caseNo: null,
      history: null,
      phone: null,
      patientPhotoInformation: this.patientPhotoInformation
    };
  }

  loadNext() {
    this.loading.show();
    this.patientService.getAllPatients().subscribe(res => {
      this.patientInformation = new MatTableDataSource(res);
      this.patientInformation.sort = this.sort;
      this.patientInformation.paginator = this.paginator;
      this.loading.hide();
    }, error => {
      this.toasterService.error("Failed", error.error);
      this.loading.hide();
    })
  }

  applyFilter(event: Event) {
    const filterValue = (event.target as HTMLInputElement).value;
    this.patientInformation.filter = filterValue.trim().toLowerCase();
  }

  openAddPatientDialog() {
    this.initData();
    const dialogRef = this.dialog.open(EditPatientComponent, {
      disableClose: true,
      data: this.patientData
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result) {
        this.loadNext();
      }
    });
  }

  OnRowClick(patient: GetPatientInformationModel) {
    this.loading.show();
    this.router.navigate(['patient/details', patient.id])
    this.loading.hide();
  }

  onPatientEdit(patient: GetPatientInformationModel = {
    id: new GuidModel().Empty,
    firstName: null,
    lastName: null,
    email: null,
    age: null,
    gender: null,
    caseNo: null,
    history: null,
    phone: null,
    patientPhotoInformation: null
  }) {
    const dialogRef = this.dialog.open(EditPatientComponent, {
      disableClose: true,
      data: patient
    });

    dialogRef.afterClosed().subscribe(result => {
      if (result) {
        this.loadNext();
      }
    });
  }

  onPatientDelete(patientId: string) {
    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      disableClose: true,
      data: { title: 'Delete Patient', message: 'Are you sure you want to delete the patient along with all the treatment and record information' }
    });
    dialogRef.afterClosed().subscribe(result => {
      if (result) {
        this.loading.show();
        this.patientService.deletePatient(patientId).subscribe(() => {
          this.loadNext();
          this.toasterService.success("Success", "Patient information deleted successfully");
          this.loading.hide();
        }, error => {
          this.toasterService.error("Failed", error.error);
          this.loading.hide();
        })
      }
    });
  }

  onPatientDetails(patientId: string) {
    this.loading.show();
    this.router.navigate(['patient/details', patientId])
    this.loading.hide();
  }
}

对话框.ts

<div *ngIf="patientInformationFormGroup">
    <button class="close" mat-button (click)="onDialogClose()">X</button>
    <h2 mat-dialog-title>{{dialogTitle}}

    </h2>
    <mat-dialog-content class="mat-typography">
        <!-- <mat-card> -->
        <!-- <mat-card-content> -->
        <form *ngIf="patientInformationFormGroup" [formGroup]="patientInformationFormGroup" class="patient-form">

            <!-- <ng-template matStepLabel>Patient Information</ng-template> -->
            <h3 class="mb-3 text-uppercase bg-light p-2"><i class="mdi mdi-office-building mr-1"></i> Patient
                Information
                (Required)</h3>
            <div class="row">
                <div class="col-md-6">
                    <mat-form-field appearance="outline">
                        <mat-label>First Name</mat-label>
                        <input matInput formControlName="firstName" placeholder="Enter First Name" required>
                        <mat-error
                            *ngIf="patientInformationFormGroup.get('firstName').invalid && (patientInformationFormGroup.get('firstName').dirty || patientInformationFormGroup.get('firstName').touched) && patientInformationFormGroup.get('firstName').errors.required">
                            First name is required
                        </mat-error>
                        <!-- <mat-icon matSuffix>sentiment_very_satisfied</mat-icon> -->
                        <!-- <mat-hint>Hint</mat-hint> -->
                    </mat-form-field>
                </div>
                <div class="col-md-6">
                    <mat-form-field appearance="outline">
                        <mat-label>Last Name</mat-label>
                        <input matInput formControlName="lastName" placeholder="Enter Last Name" required>
                        <mat-error
                            *ngIf="patientInformationFormGroup.get('lastName').invalid && (patientInformationFormGroup.get('lastName').dirty || patientInformationFormGroup.get('lastName').touched) && patientInformationFormGroup.get('lastName').errors.required">
                            First name is required
                        </mat-error>
                    </mat-form-field>
                </div>
            </div>
            <div class="row">
                <div class="col-md-4">
                    <mat-form-field appearance="outline">
                        <mat-label>Phone</mat-label>
                        <input matInput formControlName="phone" placeholder="Enter phone" required>
                        <mat-error
                            *ngIf="patientInformationFormGroup.get('phone').invalid && (patientInformationFormGroup.get('phone').dirty || patientInformationFormGroup.get('phone').touched) && patientInformationFormGroup.get('phone').errors.required">
                            Phone number is required
                        </mat-error>
                        <mat-error
                            *ngIf="patientInformationFormGroup.get('phone').invalid && (patientInformationFormGroup.get('phone').dirty || patientInformationFormGroup.get('phone').touched) && patientInformationFormGroup.get('phone').errors.pattern">
                            Please Enter valid phone number
                        </mat-error>
                    </mat-form-field>
                </div>
                <div class="col-md-4">
                    <mat-form-field appearance="outline">
                        <mat-label>Age</mat-label>
                        <input matInput formControlName="age" placeholder="Enter Age" required>
                        <mat-error
                            *ngIf="patientInformationFormGroup.get('age').invalid && (patientInformationFormGroup.get('age').dirty || patientInformationFormGroup.get('age').touched) && patientInformationFormGroup.get('age').errors.required">
                            Age is required
                        </mat-error>
                        <mat-error
                        *ngIf="patientInformationFormGroup.get('age').invalid && (patientInformationFormGroup.get('age').dirty || patientInformationFormGroup.get('age').touched) && patientInformationFormGroup.get('age').errors.pattern">
                        Enter valid age
                    </mat-error>
                    </mat-form-field>
                </div>
                <div class="col-md-4">
                    <mat-form-field appearance="outline">
                        <mat-label>Gender</mat-label>
                        <mat-select formControlName="gender" name="gender" required>
                            <mat-option>--</mat-option>
                            <mat-option *ngFor="let gender of genders" [value]="gender.id">
                                {{gender.name}}
                            </mat-option>
                        </mat-select>
                        <mat-error
                            *ngIf="patientInformationFormGroup.get('gender').invalid && (patientInformationFormGroup.get('gender').dirty || patientInformationFormGroup.get('gender').touched) && patientInformationFormGroup.get('gender').errors.required">
                            Gender is required
                        </mat-error>
                    </mat-form-field>
                </div>
            </div>

            <h3 class="mb-3 text-uppercase bg-light p-2"><i class="mdi mdi-office-building mr-1"></i> Patient
                Information
                (Optional)</h3>
            <div class="row">
                <div class="col-md-6">
                    <mat-form-field appearance="outline">
                        <mat-label>Email</mat-label>
                        <input matInput formControlName="email" placeholder="Enter Email">
                        <mat-error
                        *ngIf="patientInformationFormGroup.get('email').invalid && (patientInformationFormGroup.get('email').dirty || patientInformationFormGroup.get('email').touched) && patientInformationFormGroup.get('email').errors.email">
                        Please enter valid email
                    </mat-error>
                    </mat-form-field>
                </div>
                <div class="col-md-6">
                    <mat-form-field appearance="outline">
                        <mat-label>Case No</mat-label>
                        <input matInput formControlName="caseNo" placeholder="Enter Case No">
                    </mat-form-field>
                </div>
            </div>
            <div class="row mb-3">
                <div class="col-md-6">
                    <div class="custom-file">
                        <input formControlName="photo" accept="image/*" type="file" class="custom-file-input"
                            id="customFile" (change)="onPatientPhotoChange($event)">
                        <label class="custom-file-label" for="customFile">Choose Patient image</label>
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="profile-image-section">
                        <input id="imageUpload" type="file" />
                        <div *ngIf="imageUrl != null" class="profile-image img-wrap">
                            <span class="close" (click)="onImageDelete(patientInformation.patientPhotoInformation.id)">&times;</span>
                            <img for="imageUpload" [src]="imageUrl" alt="Profile Image" class="profile-image">
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <mat-form-field appearance="outline">
                        <mat-label>History</mat-label>
                        <textarea matInput formControlName="history" placeholder="Enter History"></textarea>
                    </mat-form-field>
                </div>
            </div>
        </form>
    </mat-dialog-content>
    <mat-dialog-actions align="end">
        <button mat-raised-button mat-dialog-close>Cancel</button>
        <button mat-raised-button (click)="onSavePatientInformation()" cdkFocusInitial color="primary">Submit</button>
    </mat-dialog-actions>
</div>

对话框.html

import { Component, OnInit, Input, Inject } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { PatientService } from '../patient.service';
import { LoadingService } from 'src/app/shared/loading.service';
import { GetGenderInformationModel } from 'src/app/models/common/GetGenderInformationModel';
import { GuidModel } from 'src/app/models/common/GuidModel';
import { GetPatientInformationModel } from 'src/app/models/patient/GetPatientInformationModel';
import { PostPatientInformationModel } from 'src/app/models/patient/PostPatientInformationModel';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { AppconfigService } from 'src/app/shared/appconfig.service';
import { ToasterService } from '../../shared/toaster.service';
import { ConfirmDialogComponent } from '../../shared/components/confirm-dialog/confirm-dialog.component';

@Component({
  selector: 'app-edit-patient',
  templateUrl: './edit-patient.component.html',
  styleUrls: ['./edit-patient.component.scss']
})
export class EditPatientComponent implements OnInit {

  public dialogTitle: string;
  genders: GetGenderInformationModel[];
  patientInformationFormGroup: FormGroup;
  patientImage: File;
  apiUrl: string;
  public imageUrl: string

  constructor(private _formBuilder: FormBuilder,
    private patientService: PatientService,
    private loading: LoadingService,
    private appConfigService: AppconfigService,
    public dialogRef: MatDialogRef<EditPatientComponent>,
    @Inject(MAT_DIALOG_DATA) public patientInformation: GetPatientInformationModel,
    private toasterService: ToasterService,
    public dialog: MatDialog,) { }

  ngOnInit() {
    this.loading.show();
    this.apiUrl = this.appConfigService.apiBaseUrl
    if (this.patientInformation.id == new GuidModel().Empty) {
      this.dialogTitle = "Add Patient"
      this.imageUrl = null;
    }
    else {
      this.dialogTitle = "Edit Patient"
      if (this.patientInformation.patientPhotoInformation != null) {
        this.imageUrl = `${this.apiUrl}${this.patientInformation.patientPhotoInformation.path}/${this.patientInformation.patientPhotoInformation.name}`
      }
      else {
        this.imageUrl = null;
      }
    }
    this.patientService.getGender().subscribe(res => {
      this.genders = res;
      this.initForm()
      this.loading.hide();
    }, error => {
      this.toasterService.error("Failed", error.error);
      this.loading.hide();
      this.dialogRef.close();
    })
  }

  onImageDelete(imageId: string) {
    const dialogRef = this.dialog.open(ConfirmDialogComponent, {
      disableClose: true,
      data: { title: 'Delete Image?', message: 'Are you sure you want to delete the patient photo' }
    });
    dialogRef.afterClosed().subscribe(result => {
      if (result) {
        this.loading.show();
        this.patientService.deletePatientPhoto(imageId).subscribe(() => {
          this.patientInformation.patientPhotoInformation = null;
          this.imageUrl = null;
          this.loading.hide();
        }, error => {
          this.toasterService.error("Failed", error.error);
          this.loading.hide();
        })
      }
    })

  }

  initForm() {
    this.patientInformationFormGroup = this._formBuilder.group({
      id: [this.patientInformation.id],
      firstName: [this.patientInformation.firstName == null ? null : this.patientInformation.firstName, [Validators.required, Validators.maxLength(10)]],
      lastName: [this.patientInformation.lastName == null ? null : this.patientInformation.lastName, Validators.required],
      email: [this.patientInformation.email == null ? null : this.patientInformation.email, Validators.email],
      age: [this.patientInformation.age == null ? null : this.patientInformation.age, [Validators.required, Validators.pattern("^[0-9*]+$")]],
      phone: [this.patientInformation.phone == null ? null : this.patientInformation.phone, [Validators.required, Validators.pattern("^[0-9*-+,]+$")]],
      gender: [this.patientInformation.gender == null ? null : this.patientInformation.gender, Validators.required],
      history: [this.patientInformation.history == null ? null : this.patientInformation.history],
      caseNo: [this.patientInformation.caseNo == null ? null : this.patientInformation.caseNo],
      photo: ['']
    });
  }

  onPatientPhotoChange(e) {
    const files = e.target.files;
    if (e.target.files == 0) {
      return
    }
    this.patientImage = files[0];
  }

  onDialogClose() {
    this.dialogRef.close();
  }

  onSavePatientInformation() {
    if (this.patientInformationFormGroup.invalid) {
      Object.keys(this.patientInformationFormGroup.controls).forEach(field => {
        const control = this.patientInformationFormGroup.get(field);
        control.markAsTouched({ onlySelf: true });
      });
      this.toasterService.warning("Warning", "There are errors in the form");
    }
    else {
      this.loading.show();
      this.patientService.savePatientInformation(this.prepareToSendPatientInformation()).subscribe(() => {
        this.loading.hide();
        this.toasterService.success("Sucess", "Changes Saved")
        this.dialogRef.close(true);
      }, error => {
        this.toasterService.error("Failed", error.error);
        this.loading.hide();
       })
    }
  }

  prepareToSendPatientInformation(): PostPatientInformationModel {
    let patientInformationFormData = this.patientInformationFormGroup.value;

    let postPatientInformation = {
      id: patientInformationFormData.id,
      firstName: patientInformationFormData.firstName,
      lastName: patientInformationFormData.lastName,
      age: patientInformationFormData.age,
      gender: patientInformationFormData.gender,
      email: patientInformationFormData.email,
      phone: patientInformationFormData.phone,
      history: patientInformationFormData.history,
      caseNo: patientInformationFormData.caseNo,
      patientPhoto: this.patientImage != null ? this.patientImage : null
    };
    return postPatientInformation;
  }

}

加吉尔

根据我从您的代码中了解到的情况,在接近更新数据时调用了 function loadNext

dialogRef.afterClosed().subscribe(result => {
      if (result) {
        this.loadNext();
      }
    });

因此,在您关闭对话框后,表格将始终加载最近的数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM