2017-03-31 46 views
0

更新:Link to Plunker角ControlValueAccessor registerOnChange回調被覆蓋

運行到一個奇怪的問題。我正在使用Angular 2.4.1。當組件最初加載時,值設置器運行並正確觸發onChangeCallback。不過,我在consoleChangeChangeCallback上進行日誌記錄,並且在初始設置之後,它將被替換爲匿名函數。

下面是的console.log的結果:

  1. 功能(_){}
  2. 功能(newValue)以{ dir.viewToModelUpdate(NEWVALUE); control.markAsDirty(); control.setValue(newValue,{emitModelToViewChange:false}); }

  3. 功能(_){}

第一發生在頁面加載,隨後立即2.我假設角是處理該令牌,並且在該點上正確執行ControlValueAccessor。當我然後在select元素上進行更改時,onChangeCallback將作爲匿名函數再次被調用,而不添加ControlValueAccessor。

關於如何解決這個問題的任何想法?這只是這種形式控制,我遇到了這個問題。

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

@Component({ 
    selector: 'select-resizable', 
    template:` 
    <select #mainSelectElement [(ngModel)]="value" (change)="updateSelected($event.target.value)" style="width: initial;"> 
     <ng-content></ng-content> 
    </select> 
    <select class="usa-sr-only" aria-hidden="true" role="presentation" #hiddenSelectElement style="width: initial;"> 
     <option>{{value}}</option> 
    </select> 
    `, 
    providers: [ 
    { provide: NG_VALUE_ACCESSOR, useClass: forwardRef(() => SelectResizableComponent), multi: true } 
    ] 
}) 
export class SelectResizableComponent implements ControlValueAccessor { 

    @ViewChild('hiddenSelectElement') hiddenSelectElement: ElementRef; 
    @ViewChild('mainSelectElement') mainSelectElement: ElementRef; 

    private _selected: any; 

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

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

    set value(val: any) { 
    this._selected = val; 
    this.onChangeCallback(val); 
    console.log(this.onChangeCallback); 
    } 

    constructor(private renderer: Renderer, private ref: ChangeDetectorRef) {} 

    updateSelected(event) { 
    this.ref.detectChanges(); 
    const width = (this.hiddenSelectElement.nativeElement.clientWidth * 1.02) + 'px'; 
    this.renderer.setElementStyle(this.mainSelectElement.nativeElement, 'width', width); 
    } 

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

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

    registerOnTouched(fn: any) { 
    this.onTouchedCallback = fn; 
    } 
} 
+0

您是否多次使用'SelectResizableComponent'? console.log可以從組件的第二次使用中運行。 – Adam

+0

不,它只被使用一次。每次我選擇一個新項目時,調用者都會被調用,並且會調用一個空的回調函數。你可以在我剛剛添加的蹦牀上玩。 –

+1

我設置了一個getter和setter來查看函數是否正在更改,但事實並非如此。 https://plnkr.co/edit/kE2wDNAsiczDmRqCXm67?p=preview我沒有給你答案,但有兩個實例是由於某種原因而創建的,這是開始調查的地方。 – Adam

回答

2
providers: [ 
    { provide: NG_VALUE_ACCESSOR, useClass: forwardRef(() => SelectResizableComponent), multi: true } 
    ] 

問題就在那裏。我提供了令牌useClass而不是useExisting。因此,在實例化組件後,會從NG_VALUE_ACCESSOR標記的組件類中創建一個新值。

謝謝Adam,因爲發現我有兩個值。