使用Angular CDK的CdkDialog,快速实现对话框
这是Angular Advent Calendar 2023第8天的文章。
首先
今年的 Angular 有很多令人期待的功能,例如 Signal 和 Control Flow等等。雖然對這些新功能很感興趣,但由於其他人已經不斷地撰寫出色的文章,所以我打算再次致力於推廣 Angular CDK。
我们将使用CdkDialog来实现在创建应用程序时必要的模态对话框。
※ 我会先放置已经完成的东西。
显示对话框
只需要准备好要显示在对话框中的组件,CdkDialog只需要几行代码就可以实现,让我们马上试一试。
创建要在对话框中显示的组件
@Component({
selector: 'app-dialog',
standalone: true,
template: `
<div style="background-color: white; padding: 24px;">
<p>Dialog by CdkDialog</p>
</div>
`,
})
export class DialogComponent {}
使用 CdkDialog 的 open() 方法进行调用
import { DialogModule, Dialog } from '@angular/cdk/dialog';
@Component({
selector: 'app-root',
standalone: true,
template: `
<button (click)="openDialog()">Open Dialog</button>
`,
imports: [DialogModule],
})
export class App {
private readonly dialog = inject(Dialog);
openDialog() {
this.dialog.open(DialogComponent);
}
}
只需要这些,就可以实现一个简单的模态对话框。比你想象的要简单得多。
外表的统一化
通过使用 CdkDialog,您可以使用 DialogConfig 的 container 选项来实现共同的外观。
import { PortalModule } from '@angular/cdk/portal';
@Component({
selector: 'app-dialog-container',
standalone: true,
template: `
<div style="background-color: white; padding: 24px;">
<ng-template cdkPortalOutlet></ng-template>
</div>
`,
imports: [PortalModule],
})
export class DialogContainer extends CdkDialogContainer {}
创建一个继承自CdkDialogContainer的组件,然后只需将其指定为container选项。
openDialog() {
this.dialog.open(DialogComponent, {
container: DialogContainer
});
}
您可以使用這個方法來統一所有對話框的外觀。
行为的标准化
可以通过在DialogContainer中实现诸如“按下ESC按钮将关闭”等对话框常见的行为,轻松实现共通化。
import { DialogRef } from '@angular/cdk/dialog';
import { ESCAPE } from '@angular/cdk/keycodes';
export class DialogContainer extends CdkDialogContainer {
private readonly dialogRef = inject(DialogRef);
@HostListener('keydown', ['$event'])
handleKeydown(event: KeyboardEvent) {
const { keyCode } = event;
if (keyCode === ESCAPE) {
this.dialogRef.close();
}
}
}
※ DialogRef在实现自定义对话框方面非常便利,但本次说明省略。如果您有兴趣,可以参考官方文档。
方法
标准化呼叫
为了防止调用者代码的冗余,我们可以创建一个服务。
@Injectable({
providedIn: 'root',
})
export class DialogService {
private readonly dialog = inject(Dialog);
open<C>(component: ComponentType<C>) {
return this.dialog.open(component, {
container: DialogContainer,
});
}
}
private readonly dialog = inject(DialogService);
openDialog() {
this.dialog.open(DialogComponent);
}
通过这样的调用方式,不仅可以使调用更加清晰简洁,还能隐藏详细的设置等细节。
总结
这次再次使用CdkDialog进行通用化,我自己也觉得这么简单吗?我非常惊讶。
Angular CDK的文章还很少,可能给人一种不好接触的印象,但是像这次的CdkDialog一样,有很多简单而方便的功能。
特别是对话框的共通化属于相对较高难度的类别,所以请务必尝试使用CdkDialog。
明天是@scrpgil!