【问题标题】:Custom Form Input not binding to model自定义表单输入未绑定到模型
【发布时间】:2018-06-30 09:44:27
【问题描述】:

我正在尝试在 Angular 4 中进行自定义表单输入。这是一个简单的示例,但我无法让组件绑定到 ngModel。我可以从父控制器向该组件传递一个默认值,但是当我更改此输入中的值时,UI 会注册更改,但控制器中的模型未显示新值。

这是我的自定义组件:

import { Component, Input, forwardRef, Output, EventEmitter, ElementRef, Renderer } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl } from '@angular/forms';

@Component({
    selector: 'input-test2',
    template:
        `
           <input type="text" class="form-control" placeholder="Symbol"  [(ngModel)]="value" [maxlength]="5" >     
        `,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => InputTestComponent),
            multi: true
        },
    ]
})
export class InputTestComponent implements ControlValueAccessor {
    @Input('value') value = false;
    
    private propagateChange = (_: any) => { };
    private propagateTouch = (_: any) => { };
    
    writeValue(value: any): void {
        if (value) {
            this.value = value;
        }
    }
    
    registerOnChange(fn: (_: any) => void): void {
        this.propagateChange = fn;
    }
    registerOnTouched(fn: () => void): void {
        this.propagateTouch = fn;
    }
    
    private onChange(event : any) {
        this.propagateChange(this.value);
    }

还有我对组件的使用: .. 在表单中

&lt;input-test2 id="coin" name="coin" [(ngModel)]="manualEntry.coin" #coin="ngModel" required (change)="x($event)" &gt; &lt;/input-test2&gt;

有没有人有一个如何做这个自定义表单输入的简单例子?我发现的所有示例要么很复杂,要么遗漏了功能。我只想要一个默认输入 type="text" 开始,然后我可以添加到这个。

【问题讨论】:

  • 你永远不会调用propagateChange和propagateTouch。您必须在每次值更改时调用前者,而在输入模糊时调用后者。您还应该处理禁用状态。
  • 必须在自定义表单控件的模板中添加(input)="onChange()
  • 模糊和变化似乎同时触发,没有另一个我不能让一个触发,这是预期的吗?

标签: angular angular4-forms


【解决方案1】:

感谢上面的 cmets。现在按预期工作。这似乎是一个很好的 sn-p,它提供了 input type="text" 的基本实现:

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

@Component({
    selector: 'input-test2',
    template:
        `
           <input type="text" class="form-control" placeholder="Symbol"  [(ngModel)]="value" [maxlength]="5" (change)="onChange($event)" [disabled]="isDisabled" >     
        `,
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => InputTestComponent),
            multi: true
        },
    ]
})
export class InputTestComponent implements ControlValueAccessor {
    @Input('value') value = false;
    
    private propagateChange = (_: any) => { };
    private propagateTouch = (_: any) => { };
    private isDisabled: boolean = false;
    
    constructor(){

    }
    writeValue(value: any): void {
        if (value) {
            this.value = value;
        }
    }
    
    registerOnChange(fn: (_: any) => void): void {
        this.propagateChange = fn;
    }
    registerOnTouched(fn: () => void): void {
        this.propagateTouch = fn;
    }
    
    private onChange(event : any) {
        this.propagateChange(this.value);
    }

    private onTouch(event : any){
        this.propagateTouch(event);
    }

    setDisabledState(isDisabled: boolean): void {
        this.isDisabled = isDisabled;
      }



}

并且该组件的用法可以以这样的形式使用:

<input-test2 
       type="text"  
       id="coin" name="coin"  
       [(ngModel)]="manualEntry.coin"  
       #coin="ngModel" 
       required [disabled]="false" 
       (change)="test($event)">
</input-test2>

我希望对此有更好的说明,因为我觉得这是在表单中创建自定义/可重用组件的一种相当普遍的做法。

【讨论】:

  • 抱歉,它不起作用。当我更改值并提交表单时,它没有值。
  • 糟糕,只需添加 (change)="onChange($event)" 即可。但是除了使用(change)=...之外还有其他方法吗
  • 确保组件上有ngModel,否则表单提交时不会保存值。
猜你喜欢
  • 2020-08-29
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 2018-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多