如何通过无输入的自定义控件以角度形式触发change()

Ste*_*fan 3 javascript forms angular

我确实想创建一个不包含任何输入的自定义控件。每当控件更改时,我都希望保存完整的表单。

我们当前的方法使用如下形式的事件更改:

 <form #demoForm="ngForm" (change)="onChange()">
      <custom-input name="someValue" [(ngModel)]="dataModel">
      </custom-input>
 </form>
Run Code Online (Sandbox Code Playgroud)

如您所见,我们使用“ change”事件来响应表单中的任何更改。只要我们具有输入,复选框,...作为控件,此方法就可以正常工作。

但是我们的自定义控件仅存在于我们可以单击的简单div之外。每当我单击div时,控件的值都会增加1。但是不会触发表单的“更改”事件。我是否必须以某种方式将我的自定义控件链接到表单?还是有需要触发的事件?

import { Component, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

@Component({
    selector: 'custom-input',
    template: `<div (click)="update()">Click</div>`,
    providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => CustomInputComponent),
        multi: true
    }]
})
export class CustomInputComponent implements ControlValueAccessor {

    private onTouchedCallback: () => void = () => {};
    private onChangeCallback: (_: any) => void = () => {};

    update(){
      this.value++;
    }

    get value(): any {
        return this.innerValue;
    };

    set value(v: any) {
        console.log("Change to");
        if (v !== this.innerValue) {
            this.innerValue = v;
            this.onChangeCallback(v);
        }
    }

    writeValue(value: any) {
        if (value !== this.innerValue) {
            this.innerValue = value;
        }
    }

    registerOnChange(fn: any) {
        this.onChangeCallback = fn;
    }

    registerOnTouched(fn: any) {
        this.onTouchedCallback = fn;
    }
}
Run Code Online (Sandbox Code Playgroud)

我创建了一个插件来演示该问题:https ://plnkr.co/edit/ushMfJfcmIlfP2U1EW6A

每当您单击“单击”时,模型值都会增加,但控制台上没有输出,因为不会触发变更事件...(有一个console.log链接到变更事件)

Ste*_*fan 6

多谢您的回覆。

最终,我找到了解决该问题的以下解决方案:正如注释中提到的Claies一样,我的自定义组件不会触发change事件。因此,表格永远不知道更改。这与角度无关,但是可以说输入/表单的预期行为。

最简单的解决方案是在发生更改时在customcontrol中触发更改事件:

constructor(private element: ElementRef, private renderer: Renderer) {
}

public triggerChanged(){
    let event = new CustomEvent('change', {bubbles: true});
    this.renderer.invokeElementMethod(this.element.nativeElement, 'dispatchEvent', [event]);
}
Run Code Online (Sandbox Code Playgroud)

就是这样,每当我在自定义组件中调用“ onControlChange(..)”时,我随后都会触发此事件。

请注意,您需要Custom-Event-Polyfill来支持IE! https://www.npmjs.com/package/custom-event-polyfill