[英]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)">×</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.