【问题标题】:Split components into smaller components while keeping the `ngModel` and `ngModelChange` binding of the parent components in Angular将组件拆分成更小的组件,同时保持 Angular 中父组件的 `ngModel` 和 `ngModelChange` 绑定
【发布时间】:2021-11-18 03:41:28
【问题描述】:

我有一个 main.component 需要拆分成更小的组件,同时保留父组件的 ngModelngModelChange。我怎样才能达到这样的效果?我已经尝试过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.htmlcomponentB.component.html)上的 [(ngmodel)](ngModelChange) 属性,以便实现以下目标:

<!-- main.component.html -->
<componentA [(ngModel)]="data" (ngModelChange)="method()"></componentA>
<componentB [(ngModel)]="data" (ngModelChange)="method()"></componentB>

【问题讨论】:

  • 您的较小组件需要将更改事件向上传播(@Output + EventEmitter)。
  • @GunnarB.:我试图想出一种更简洁的方法来做到这一点。我终于发现了使用 ControlValueAccessor 的正确方法。感谢您的意见!

标签: angular typescript data-binding split components


【解决方案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() {
        //...
    }
}

【讨论】:

    猜你喜欢
    • 2020-04-18
    • 2016-05-21
    • 1970-01-01
    • 2018-07-09
    • 2017-03-21
    • 2021-02-10
    • 2021-02-09
    • 2016-06-05
    • 2018-07-25
    相关资源
    最近更新 更多