3.2.对话框使用指南
在开发之中,常常会使用到对话框,创建对话框可以通过服务方式或模板方式创建。本小节中,我们来探讨一下。
一、服务方式创建(推荐使用)
关注点
使用对话框,人们常常关注的是以下问:
父组件如何传递数据给对话框?
在对话框中使用@Input() 装饰器声明对话框需要的参数
父组件中,通过 nzComponentParams 传入参数
对话框如何返回数据给父组件?
在对话框中编写方法 ,方法返回值为待返回给父组件的数据
在父组件中,通过modal.getContentComponent()或直接使用nzOnOk: (对话框组件)可以获取到对话框组件实例,通过调用步骤1中的方法获取返回值
示例
父组件部分
模板
src/app/plan/plan.component.html
<a (click)="createEditModal(data)">更新</a>
控制器
src/app/plan/plan.component.ts
import {Component, OnInit, ViewContainerRef} from '@angular/core';
import {NzModalService} from 'ng-zorro-antd/modal';
import {NzMessageService} from 'ng-zorro-antd';
@Component({
selector: 'app-plan',
templateUrl: './plan.component.html',
styleUrls: ['./plan.component.css']
})
export class PlanComponent implements OnInit {
constructor(private service: PlanService,
private modal: NzModalService,
private message: NzMessageService,
private viewContainerRef: ViewContainerRef) {
}
/**
* 创建编辑对话框
*/
createEditModal(plan: any): void {
const modal = this.modal.create({
nzTitle: '编辑计划',
// 对话框的内容,本例中为一个表单组件
nzContent: PlanUpdateComponent,
nzViewContainerRef: this.viewContainerRef,
// 父组件传递给对话框的数据
nzComponentParams: {
data: plan,
},
nzOnOk: (componentInstance: PlanUpdateComponent) => {
// 校验表单的正确性,若表单校验通过,则获取表单数据并调用api执行更新操作;否则返回false,不允许提交表单
const isValid: boolean = componentInstance.isValidForm();
if (isValid) {
const result: Plan = componentInstance.getFormData();
this.updatePlan(result.id, result);
return result;
}
return false;
}
});
// 当对话框开启时,打印日志
modal.afterOpen.subscribe(() => console.log('[afterOpen] emitted!'));
// 当对话框关闭时,返回结果
modal.afterClose.subscribe(result => console.log('[afterClose] The result is:', result));
}
}
对话框部分
模板
src/app/plan/plan-update/plan-update.component.html
<form nz-form [formGroup]="validateForm">
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="name" nzRequired>name</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid name!">
<input nz-input id="name" formControlName="name"/>
</nz-form-control>
</nz-form-item>
...
</form>
控制器
src/app/plan/plan-update/plan-update.component.ts
import {Component, Input, OnInit} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {FormUtil} from '../../../utils/form.util';
import {NzModalRef} from 'ng-zorro-antd';
@Component({
selector: 'app-plan-create',
templateUrl: './plan-create.component.html',
styleUrls: ['./plan-create.component.css']
})
export class PlanCreateComponent implements OnInit {
// 对话框需要的参数,由外部组件传入
@Input() data?: Plan;
/**
* 校验表单
*/
isValidForm(): boolean {
return this.formUtil.isValidForm(this.validateForm);
}
/**
* 获取表单数据并进行处理
*/
getFormData(): Plan {
const data: Plan = this.formUtil.getFormData(this.data, this.validateForm);
const times: any[] = this.validateForm.get('rangePicker').value;
data.startTime = times[0];
data.expireTime = times[1];
return data;
}
}
二、模板方式创建
关注点
使用对话框,人们常常关注的是以下问:
父组件如何传递数据给对话框?对话框如何返回数据给父组件?
在控制器中设置一个变量,作为父模板和对话框模板之间的桥梁
在父模板或对话框模板中,改变变量的值,达到数据传递的作用
示例
模板
<!-- 父模板部分 -->
<button nz-button nzType="primary" (click)="showUpdateModal()">
<!-- 对话框模板部分 -->
<nz-modal
[(nzVisible)]="isUpdateModalVisible"
nzTitle="Modal Title"
(nzOnCancel)="handleUpdateCancel()"
(nzOnOk)="handleUpdateOk()"
[nzOkLoading]="isOkUpdateModalLoading>
<form nz-form [formGroup]="validateForm">
<nz-form-item>
<nz-form-label [nzSm]="6" [nzXs]="24" nzFor="name" nzRequired>name</nz-form-label>
<nz-form-control [nzSm]="14" [nzXs]="24" nzErrorTip="The input is not valid name!">
<input nz-input id="name1" formControlName="name" [ngModel]="waitingUpdatedData?.name"/>
</nz-form-control>
</nz-form-item>
...
</nz-modal>
控制器
import {Component, OnInit, ViewContainerRef} from '@angular/core';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
@Component({
selector: 'app-plan',
templateUrl: './plan.component.html',
styleUrls: ['./plan.component.css']
})
export class PlanComponent implements OnInit {
// 控制对话框是否可见
isUpdateModalVisible = false;
// 控制对话框
isOkUpdateModalLoading = false;
// 对话框和父组件之间的桥梁,用于传递数据
waitingUpdatedData: any;
validateForm!: FormGroup;
constructor(private fb: FormBuilder) {
}
ngOnInit(): void {
this.validateForm = this.fb.group({
name: [null, [Validators.required]],
expectedValue: [null, [Validators.required]],
rangePicker: [[]],
description: [null, [Validators.required]],
});
...
}
/**
* 显示对话框
*/
showUpdateModal(id: string, data: any): void {
// 初始化对话框所需的数据
const dateRange: Date[] = [new Date(data.startTime), new Date(data.expireTime)];
data['dateRange'] = dateRange;
this.waitingUpdatedData = data;
console.log(this.waitingUpdatedData)
// 手动设置对话框可见
this.isUpdateModalVisible = true;
}
/**
* 表单提交
*/
submitUpdateForm(): void {
this.waitingUpdatedData.startTime = this.waitingUpdatedData.dateRange[0];
this.waitingUpdatedData.expireTime = this.waitingUpdatedData.dateRange[1];
this.updatePlan(this.waitingUpdatedData.id, this.waitingUpdatedData);
}
/**
* 重置表单
*/
resetForm(): void {
this.validateForm.reset();
for (const key in this.validateForm.controls) {
this.validateForm.controls[key].markAsPristine();
this.validateForm.controls[key].updateValueAndValidity();
}
}
/**
* 处理ok时间
*/
handleUpdateOk(): void {
// 显示加载中
this.isOkUpdateModalLoading = true;
// 等待1秒,用于模拟请求api所需时间。 1秒后,提交表单数据,手动隐藏对话框,并重置表单
setTimeout(() => {
this.submitUpdateForm();
this.isUpdateModalVisible = false;
this.isOkUpdateModalLoading = false;
this.resetForm();
}, 1000);
}
/**
* 处理取消事件
*/
handleUpdateCancel(): void {
// 设置对话框不可见,并重置表单
this.isUpdateModalVisible = false;
this.resetForm();
}
}
三、对比
相比服务方式,模板方式创建对话框代码不够优雅
服务方式创建对话框只需要一个方法,而模板方式却需要1-2个变量、4-5个方法
模板方式需要在控制器中,手动通过变量控制对话框的显示和消失
模板方式需要手动重置表单
Last updated
Was this helpful?