【问题标题】:Change not detected on custom form input自定义表单输入未检测到更改
【发布时间】:2018-07-01 08:00:08
【问题描述】:

我有一个 Angular 4 的自定义表单输入。单击此元素上的嵌入式下拉菜单时,我无法传播更改。如果我使用最后一个选项“添加自定义”然后手动输入值,我只能得到更改。一旦我这样做并专注于元素,更改就会按预期工作。

这是我设置的一个简单示例。当我向该组件添加更多细节时,例如单击以选择的下拉列表,更改不会流回父控制器。 注意,模型总是会正确更新,但我没有触发更改功能。

Link to simple input exapmple

我不确定为什么“SetKnownCoin”函数不会传播更改。我错过了什么吗?

import { Component, Input, forwardRef, ElementRef, Renderer } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Coin2 } from '../../../models/config';

@Component({
    selector: 'input-coin',
    template:
        `
        <div class="input-coin col-xs-12">
            <div class="input-coin-symbol col-xs-6">
                <div class="dropdown">
                    <input type="text" class="form-control dropdown-toggle" placeholder="Symbol"  [(ngModel)]="value" [maxlength]="5" 
                    (change)="update()" 
                    [disabled]="isDisabled" (click)="getSymbol()" data-toggle="dropdown" > 
                    <ul class="dropdown-menu">
                        <li *ngFor="let c of coins" (click)="setKnownCoin(c)">{{c.symbol}} - {{c.name}}</li>
                        <li role="separator" class="divider"></li>
                        <li (click)="setCustom()">Add Custom</li>
                    </ul>
                </div>
            </div>
            <div class="input-coin-name col-xs-6"> {{coinName}}</div>
        </div>    
        `,
    styles: [
        `
                .defaultLabel{
                    color:#848484;
                }
                .input-coin {
                    width: 100%;
                    height: 34px;
                    display: block;       
                }
                .input-coin, .input-coin-symbol{
                    padding-left:0;
                }
                .input-coin-symbol > .dropdown > ul {
                    padding-top:0;
                    margin-top:0;
                    border-color: #66afe9;
                }
                .input-coin > .input-coin-symbol > .dropdown > ul > li {
                    padding: 4px 2px 4px 12px;
                }
                .input-coin > .input-coin-symbol > .dropdown > ul > li.divider {
                    padding-top: 0;
                    padding-bottom: 0;
                }
                .input-coin > .input-coin-symbol > .dropdown > ul > li:hover {
                    background-color:#D8D8D8;
                }
                .input-coin > .input-coin-name {
                    padding: 6px 12px 6px 2px;
                }
                `
    ],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => InputCoinComponent),
            multi: true
        },
    ]
})
export class InputCoinComponent implements ControlValueAccessor {
    @Input('value') value: string = "";

    propagateChange = (_: any) => { };
    propagateTouch = (_: any) => { };
    isDisabled: boolean = false;
    coinName: string = "";
    coins: Coin2[];

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

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

    registerOnChange(fn: (_: any) => void): void {
        this.propagateChange = fn;
    }
    registerOnTouched(fn: () => void): void {
        this.propagateTouch = fn;
    }

    update() {
        this.value = this.value.toUpperCase();
        this.propagateChange(this.value);
    }

    onTouch(event: any) {
        this.value = this.value.toUpperCase();
        this.propagateTouch(event);
    }

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

    getSymbol() {
        var coins: Coin2[] = [{ symbol: 'USD', name: 'US Dollar' }, { symbol: 'BTC', name: 'Bitcoin' }, { symbol: 'ETH', name: 'Ethereum' },
        { symbol: 'XRP', name: 'Ripple' }, { symbol: 'ADA', name: 'Cardano' }];
        this.coins = coins;
    }

    setKnownCoin(c: any) {
        this.value = c.symbol;
        this.coinName = c.name;
        this.propagateChange(this.value);
    
    }

    setCustom() {
        this.value = "";
        this.coinName = "";
        this.propagateChange(this.value);
        this.renderer.invokeElementMethod(this.elRef.nativeElement.querySelector('input'), 'focus', []);
    }


}

我对这个组件的使用:

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

【问题讨论】:

  • 显然,如果我使用 (ngModelChange) 而不是 (change),则此代码效果很好。

标签: angular angular4-forms


【解决方案1】:

显然,如果我使用 (ngModelChange) 而不是 (change),则此代码 效果很好。

(change) 是一个 DOM 事件,而 (ngModelChange) 是一个 Angular 表单更改事件(与您的数据结构相关)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    相关资源
    最近更新 更多