将组件拆分成更小的组件,同时保持 Angular 中父组件的 `ngModel` 和 `ngModelChange` 绑定
Posted
技术标签:
【中文标题】将组件拆分成更小的组件,同时保持 Angular 中父组件的 `ngModel` 和 `ngModelChange` 绑定【英文标题】:Split components into smaller components while keeping the `ngModel` and `ngModelChange` binding of the parent components in Angular 【发布时间】:2021-11-18 03:41:28 【问题描述】:我有一个 main.component
需要拆分成更小的组件,同时保留父组件的 ngModel
和 ngModelChange
。我怎样才能达到这样的效果?我已经尝试过this,但它似乎对 ngModelChange 没有任何作用。
例子:
//main.component.ts
@Component(
selector: 'main-component',
templateUrl: './main.component.html',
styleUrls: ['./main.component.scss'],
)
export class CardRendererComponent
private data;
private method()
//...
<!-- main.component.html -->
<div class="componentA" [(ngModel)]="data" (ngModelChange)="method()"></div>
<div class="componentB" [(ngModel)]="data" (ngModelChange)="method()"></div>
我应该怎么做才能保留该子组件(componentA.component.html
和 componentB.component.html
)上的 [(ngmodel)]
和 (ngModelChange)
属性,以便实现以下目标:
<!-- main.component.html -->
<componentA [(ngModel)]="data" (ngModelChange)="method()"></componentA>
<componentB [(ngModel)]="data" (ngModelChange)="method()"></componentB>
【问题讨论】:
您的较小组件需要将更改事件向上传播(@Output + EventEmitter)。 @GunnarB.:我试图想出一种更简洁的方法来做到这一点。我终于发现了使用 ControlValueAccessor 的正确方法。感谢您的意见! 【参考方案1】:我终于找到了一种方法来正确执行此操作,而无需发出和捕获组件之间的所有事件。我将使用ControlValueAccessor
。代码留在这里给以后需要的人:
//componentA.component.ts - Child component
import Component, forwardRef from '@angular/core';
import ControlValueAccessor, NG_VALUE_ACCESSOR from '@angular/forms';
@Component(
selector: 'componentA',
template: `<input
[(ngModel)]="dataPassedByParent"
(ngModelChange)="propagateChange(dataPassedByParent)"
>`,
providers: [
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => HeadingEditorComponent),
multi: true
],
)
export class ComponentAComponent implements ControlValueAccessor
dataPassedByParent;
propagateChange = (_: any) => ;
//Triggered when a value is written
writeValue(data: any)
if (data) this.dataPassedByParent = data;
//Trigger on ngModelChange
registerOnChange(fn)
this.propagateChange = fn;
//Trigger on touched, required but not used
registerOnTouched = () => ;
constructor()
并且在父组件中:
//main.component.ts - Parentcomponent
import Component from '@angular/core';
@Component(
selector: 'componentA',
template: `
<componentA [(ngModel)]="data" (ngModelChange)="method()"></componentA>
`,
)
export class MainComponent
data;
constructor()
method()
//...
【讨论】:
以上是关于将组件拆分成更小的组件,同时保持 Angular 中父组件的 `ngModel` 和 `ngModelChange` 绑定的主要内容,如果未能解决你的问题,请参考以下文章