Angular通过DOM操作设置Material弹窗样式的替代方法

1,177 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。
场景:表格页面,点击按钮后弹窗,对该行订单的规格进行修改,因为是仓库人员使用,所以需要调大输入框的字体方便使用。
因为无法直接修改弹窗的样式SCSS(动态弹窗,有多个组件调用),所以打算采用获取DOM并设置font-size的方式。
Ps:由于中间修改的代码没有保存,问题已经解决,所以多次尝试后删除掉的代码用省略号代替

首次尝试

我先打开弹窗,找到我需要的输入框的class,然后在ts文件中获取对应的DOM:

constructor(
    private el: ElementRef,
  ) {}

  ngOnInit(): void {
    this.el.nativeElement.querySelector('.mat-form-field-infix').style.fontSize = '18px';
  }

失败了,打印出来显示获取的是null 尝试多次不同的class名以及id名之后,放弃了该方法。

第二次尝试

由于弹窗是后加载,那我将获取DOM的操作放在弹窗绑定的按钮中,并设定延时是否可取呢?

async EditSpecs(): Promise<void> {
    setTimeout(() => {
      this.el.nativeElement.querySelector('.mat-form-field-infix').style.fontSize = '18px';
    }, 1000);
}

打印出来发现并没有什么改变,即使弹窗已经完整的展示在我面前,我依旧无法获取到他的DOM

第三次尝试

和一个不使用angular开发的前端同事交流了一下,一致认为由于弹窗属于后加载的组件,所以提前获取不可取,便打算采用监听的方式:

  @ViewChild('DialogContent') dialogDiv: ElementRef;
  dialogDiv.nativeElement.style.fontSize = '18px';

这次和之前不一样了,获取的是undefined……

第四次尝试

听了另一个同事的建议,Angular会不会在弹窗加载后,弹窗会读取一次SCSS文件呢?如果可行直接在网页里根据弹窗的class进行样式设置即可。

@Component({
  ……
  encapsulation: ViewEncapsulation.None,
})
@import "src/@fuse/scss/fuse";

supplier-order-warehouse {
    …… {
        font-size: 18px !important;
    }
}

并没有生效,要么是弹窗本身的CSS覆盖了我设置的CSS,要么是根本没有读取

最终解决方案

我最终放弃了获取DOM的方案,转用传参的方式,新增一个style用来设置内联样式:

const dialogRef = this._matDialog.open(DialogFormComponent, {
      panelClass: 'dialog-form',
      width: '300px',
      data: {
        action: 'edit',
        ……
        style: 'font-size:18px'
      }
    });

在弹窗组件的ts文件中声明

styleConfig: string;
  /**
   * @param {MatDialogRef<DialogFormComponent>} matDialogRef
   * @param _data // 接收的数据
   * @param {FormBuilder} _formBuilder
   * @param general
   * @param confSvc
   */

  constructor(
    public matDialogRef: MatDialogRef<DialogFormComponent>, // 回传数据给弹框
    @Inject(MAT_DIALOG_DATA) private _data: any, // 接收弹框数据
    private _formBuilder: FormBuilder,
    public general: GeneralService,
    public confSvc: ConfigService,
  ) {
    const { action, ……, style } = _data;
    this.action = action;
    ……
    this.styleConfig = style;
    }

html文件中设置:

<mat-form-field appearance="outline" fxFlex *ngIf="form.type !== 'imgFile'; else uploadFile" …… [style]="styleConfig">
          <mat-label>{{ form.label }}</mat-label>
          <input *ngSwitchDefault [type]="form.type ? form.type : ''" ……>
          ……
</mat-form-field>

总算达成了想要的效果,其实途中就想过这个方式,但觉得有点笨属于下下之策,操作DOM逼格多高啊(不是),折腾了半个下午最终还是采用了这个方法。