Ag-grid如何在plain JS渲染器中使用Angular Material组件
问题原因
你直接通过innerHTML写入<mat-radio-button>标签的方式无法正常渲染,是因为Angular Material组件属于Angular框架组件,必须经过Angular的编译流程才能解析依赖、绑定属性、渲染为可用的DOM节点,纯JS插入的原生HTML没有经过编译步骤,只会作为普通自定义标签原样显示。
方案1:手动动态编译Angular组件(保留组件完整能力)
这种方式可以保留Material组件的全部原生能力,性能优于AgGrid官方的框架渲染器,因为你可以自主控制编译和变更检测时机,减少多余的框架开销。
前置配置
确保你所在的Angular模块已经导入了MatRadioModule,如果你使用的是Angular 13以下版本,还需要将MatRadioButton加入模块的entryComponents数组。
代码实现
首先在定义AgGrid配置的Angular组件中传入编译所需的依赖:
import { Component, Injector, ComponentFactoryResolver } from '@angular/core'; // 其他AgGrid、Material相关导入 @Component({ // 你的组件元数据配置 }) export class YourGridComponent { constructor( private injector: Injector, private componentFactoryResolver: ComponentFactoryResolver ) {} columnDefs = [ { headerName: '选项', field: 'option', cellRenderer: plainJsRadioRenderer, // 将Angular编译依赖通过参数传给渲染器 cellRendererParams: { injector: this.injector, componentFactoryResolver: this.componentFactoryResolver } } ]; }
修改你的渲染器类:
class plainJsRadioRenderer { eGui: any; radioCompRef: any; init(params) { this.eGui = document.createElement('div'); const { injector, componentFactoryResolver } = params; // 创建MatRadioButton组件工厂 const radioFactory = componentFactoryResolver.resolveComponentFactory(MatRadioButton); // 基于当前容器创建组件实例 this.radioCompRef = radioFactory.create(injector, [], this.eGui); // 自定义组件属性 this.radioCompRef.instance.label = 'Option 1'; this.radioCompRef.instance.value = params.value; // 手动触发变更检测完成渲染 this.radioCompRef.changeDetectorRef.detectChanges(); // 可选:绑定组件事件 this.radioCompRef.instance.change.subscribe((event) => { // 处理单选选中逻辑 }) } getGui() { return this.eGui; } refresh(params) { // 数据更新时手动更新组件属性 this.radioCompRef.instance.checked = params.value === 'targetValue'; this.radioCompRef.changeDetectorRef.detectChanges(); return true; } // 组件销毁时手动销毁动态创建的实例,避免内存泄漏 destroy() { if (this.radioCompRef) this.radioCompRef.destroy(); } }
如果你使用Angular 13+版本,ComponentFactoryResolver已废弃,可以直接用createComponent方法实现,代码更简洁:
// init方法修改为 init(params) { this.eGui = document.createElement('div'); const { injector, environmentInjector } = params; this.radioCompRef = createComponent(MatRadioButton, { environmentInjector: environmentInjector, hostElement: this.eGui }); // 后续属性赋值、变更检测逻辑不变 }
方案2:直接使用Material编译后的原生结构(性能最优)
如果你的需求比较简单,不需要用到Material组件的复杂绑定能力,可以直接拼接Material组件编译后的原生HTML+样式类,完全跳过框架编译步骤,性能是所有方案中最好的,仅需要自己手动处理交互逻辑:
class plainJsRadioRenderer { eGui: any; radioInput: HTMLInputElement; init(params) { this.eGui = document.createElement('div'); // 直接使用Material编译后的DOM结构和样式类 this.eGui.innerHTML = ` <div class="mat-radio-button mat-accent"> <label class="mat-radio-label"> <span class="mat-radio-container"> <span class="mat-radio-outer-circle"></span> <span class="mat-radio-inner-circle"></span> <input type="radio" class="mat-radio-input" name="radio-group" value="${params.value}"> </span> <span class="mat-radio-label-content">Option 1</span> </label> </div> `; this.radioInput = this.eGui.querySelector('input'); // 手动绑定交互事件 this.radioInput.addEventListener('change', (e) => { // 处理选中状态切换逻辑 }) } getGui() { return this.eGui; } refresh(params) { this.radioInput.checked = params.value === 'targetValue'; return true; } }
内容的提问来源于stack exchange,提问作者kk-at-cbx
相关产品推荐
相关产品推荐

