ng-zorro的drawer的黑魔法

75 阅读2分钟

各位大佬,早上好,中午好,晚上好

今天咱们来聊聊ng-zorrodrawer组件在使用服务创建时的一个小坑——自定义footer的问题。大家都知道,modal组件可以通过ModalButtonOptions来定义footer的按钮,但drawerfooter接口却不支持类似的功能。这就导致了一些场景下,我们没法像使用modal那样灵活地自定义footer

问题背景

先来看看drawermodalfooter接口定义:

  • Drawer的footer接口定义image.png

  • Modal的footer接口定义image.png

从图中可以看到,drawerfooter只支持TemplateRef,而modalfooter则支持ModalButtonOptions。这就导致了一些问题:

  1. 动态创建弹窗时:如果没有组件来定义TemplateRef,就无法自定义footer
  2. 动态创建按钮时:如果footer的按钮是动态生成的,也无法直接通过TemplateRef来实现。

解决方案:黑魔法

既然drawerfooter只支持TemplateRef,那我们就从TemplateRef入手,搞点“黑魔法”来实现类似modalModalButtonOptions功能。

第一步:定义一个drawer-footer组件

首先,我们创建一个专门用来处理footer的组件,命名为drawer-footer

HTML部分:

<ng-template #footerTpl>
  <div style="float: right">
    <button *ngFor="let item of footerBtn" nz-button nzType="item.type" (click)="item.onClick($event)" style="margin-right: 8px;" >{{ item.label }}</button>
  </div>
</ng-template>

TypeScript部分

import { Component, OnInit, Input, ViewChild, TemplateRef } from '@angular/core';

@Component({
  selector: 'drawer-footer',
  templateUrl: './drawer-footer.component.html',
  styleUrls: ['./drawer-footer.component.less']
})
export class DrawerFooterComponent implements OnInit {

  @ViewChild('footerTpl', { static: true }) footerTpl!: TemplateRef<any>;

  @Input() footerBtn = [];
  constructor() { }

  ngOnInit(): void {
    
  }
}

第二步:动态创建组件

接下来,我们通过Angular提供的ComponentFactoryResolver服务来动态创建这个drawer-footer组件。

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(DrawerFooterComponent);
const componentRef = componentFactory.create(this.injector);
componentRef.instance.footerBtn = footer;

这里的footer是我们定义的按钮数组,比如:

const footer: Array<any> = [
    {
      label: '流程图',
      type: 'text',
      onClick: () => {
        this.createModalService.openFlowModel(taskInfo.flowInstance.id, formId);
      }
    },
    {
      label: '审批意见',
      type: 'text',
      onClick: () => {
        this.createModalService.approvalOpinions(taskInfo.flowInstance.id);
      }
    }
]

第三步:使用动态创建的TemplateRef

最后,我们将动态创建的TemplateRef传递给drawernzFooter属性。

const drawer = this.drawer.create({
    nzTitle: name,
    nzContent: FormRenderComponent,
    nzWidth: this.isMobileTerminal ? '100%' : '66%',
    nzFooter: componentRef.instance.footerTpl
});

这样一来,我们就成功模拟了modalModalButtonOptions功能,实现了动态创建footer按钮的需求。

done!!

志哥我想说

通过这种“黑魔法”,我们成功绕过了drawer组件footer接口的限制,实现了类似modalModalButtonOptions功能。虽然这个方法有点绕,但在某些场景下确实能解决问题。

不过,我还是想吐槽一下:为啥ng-zorromodal可以有ModalButtonOptions,而drawer却没有呢?找了一圈资料,也没看到相关的讨论。如果有大佬知道原因,欢迎在评论区指点一二!