如何在没有输入的情况下通过自定义控件以角度形式触发 change()

新手上路,请多包涵

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

我们当前的方法使用这样的表单更改事件:

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

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

但是我们的自定义控件只存在于我们可以单击的简单 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;
    }
}

我创建了一个 plunker 来演示这个问题: https://plnkr.co/edit/ushMfJfcmIlfP2U1EW6A

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

原文由 Stefan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 262
2 个回答

感谢您的回复。

最后我找到了这个问题的以下解决方案:正如 Claies 在评论中提到的,我的自定义组件不会触发 change 事件。因此,表格永远不会知道更改。这与角度无关,但如前所述,这是输入/表单的预期行为。

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

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

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

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

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

原文由 Stefan 发布,翻译遵循 CC BY-SA 3.0 许可协议

感谢 Stefan 为我指明了正确的方向。

不幸的是,Renderer(具有 invokeElementMethod() )最近已被弃用,取而代之的是 Renderer2(没有该方法)

所以以下对我有用

this.elementRef.nativeElement.dispatchEvent(new CustomEvent('change', { bubbles: true }));

原文由 Stephen Paul 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题