使用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);
  }
}
Dialog

只需要这些,就可以实现一个简单的模态对话框。比你想象的要简单得多。

外表的统一化

通过使用 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!

广告
将在 10 秒后关闭
bannerAds