Angular 12 自定义封装mat-radio-group后ngModel绑定与change事件失效
Angular12自定义封装mat-radio组件双向绑定失效解决方案
问题根因
Angular 8+版本对Angular Material的单选组件依赖注入逻辑做了调整,原生mat-radio-button默认只会查询直接父层级的MatRadioGroup实例。你封装的my-radio-button是独立组件,内部的原生mat-radio-button和外层自定义的my-radio-group之间隔了一层自定义组件宿主,无法自动建立关联,所以选中状态无法同步到外层group,导致双向绑定和change事件失效。
具体修改方案
1. 调整my-radio-button.component.ts
注入父级MyRadioGroupComponent,手动将内部原生单选按钮注册到父group中,建立两者的关联关系:
import { Component, Input, ViewChild, OnInit, OnDestroy, Host, Optional, SkipSelf } from '@angular/core'; import { MatRadioButton } from '@angular/material/radio'; import { MyRadioGroupComponent } from './my-radio-group.component'; @Component({ selector: "my-radio-button", templateUrl: "./my-radio-button.component.html" }) export class MyRadioButtonComponent implements OnInit, OnDestroy { @Input() value: any; @Input() disabled: boolean | undefined; // 获取内部原生mat-radio-button实例 @ViewChild(MatRadioButton) nativeRadio!: MatRadioButton; constructor( // 注入父级自定义radio group @Optional() @Host() @SkipSelf() private radioGroup: MyRadioGroupComponent ) {} ngOnInit() { if (this.radioGroup) { // 将原生单选按钮注册到父group的管理列表 this.radioGroup._radios.push(this.nativeRadio); // 给原生单选按钮绑定父group关联 this.nativeRadio.radioGroup = this.radioGroup; } } ngOnDestroy() { // 组件销毁时从父group移除,避免内存泄漏 if (this.radioGroup) { const index = this.radioGroup._radios.indexOf(this.nativeRadio); if (index > -1) { this.radioGroup._radios.splice(index, 1); } } } }
2. (可选)简化方案
如果不需要自定义组件的额外逻辑,可以直接把my-radio-button改成属性型指令,直接挂载在原生mat-radio-button上,不需要处理层级注入问题,性能更好也更稳定:
@Directive({ selector: 'mat-radio-button[myRadioButton]' }) export class MyRadioButtonDirective extends MatRadioButton { // 自定义逻辑直接加在这里即可 }
使用时直接写<mat-radio-button myRadioButton [value]="1">选项1</mat-radio-button>即可。
修改完成后重新运行项目,ngModel双向绑定和change事件就可以正常触发了。
内容的提问来源于stack exchange,提问作者Hưng Triệu
相关产品推荐
相关产品推荐

