我有一个Angular 4的自定义表单输入。我无法在单击此元素上的嵌入式下拉列表时传播更改。如果我使用最后一个选项“添加自定义”然后手动键入值,我只能进行更改。一旦我这样做并将焦点放在元素上,更改就会按预期工作。
这是我设置的一个简单示例。当我向此组件添加更多详细信息(如您单击以选择的下拉列表)时,更改不会流回到父控制器。 注意,模型总是正确更新,但我没有触发更改功能。
我不确定为什么“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>
答案 0 :(得分:0)
显然,如果我使用(ngModelChange)而不是(change),则此代码 效果很好。
(change)是一个DOM事件,而(ngModelChange)是一个Angular形式的更改事件(与您的数据结构有关)。