2017-09-30 9 views
-1

私は、<data-input-text>カスタムコンポーネントを持っています。このコンポーネントには、通常モードと無効モードの2つのモードがあります。ここでテンプレート(私はそれをデモケースのためのビットを簡素化しました)です:親フォームテンプレート駆動型のカスタムControlValueAccessor

<label *ngIf="!disabled" 
    class="field-label" 
    [ngClass]="{'focused' : isFocused, 'with-errors' : errors}"> 
    <input class="field-value" 
      [type]="type" 
      [required]="required" 
      (focus)="onFocus()" 
      (blur)="onBlur()" 
      [(ngModel)]="value" 
      #fieldInput="ngModel"> 

</label> 
<div class="field-label" *ngIf="disabled"> 
    <span class="field-value">{{ value }}</span> 
    <span class="field-name">{{ label }}</span> 
</div> 

、私は次のように、このコンポーネントを使用します。

<form #profileForm="ngForm"> 
    <data-text-input 
      label="lastName" 
      [required]="true" 
      [disabled]="userIsRegistered"      
      name="lastName" 
      ngModel></data-text-input> 
</form> 

userIsRegistered入力フィールドまたはコンポーネント内のスパンを切り替えるブール値を返します。それまではすべてここまでうまくいきます。

私はこのようなBehaviorSubjectに一致するように親コンポーネントに形式を設定します。ここでは

this._sub = this.dl.selectedEmployee.subscribe(u => { 
    if (u.id) { 
    this.isLoading = false; 
     setTimeout(() => { 
     this.profileForm.setValue(u); 
     this.profileForm.control.markAsPristine(); 
     }, 10); 
    } 
}); 

はカスタムControlValueAccessor コンポーネントです:

import { Component, Input, ViewChild, forwardRef, 
     AfterViewInit, OnInit, OnChanges, 
     NgModule } from '@angular/core'; 

import { NG_VALUE_ACCESSOR, NG_VALIDATORS, 
     ControlValueAccessor, FormControl, 
     Validator, NgForm } from '@angular/forms'; 

@Component({ 
    selector: 'data-text-input', 
    template: ` 
    <label *ngIf="!disabled" 
     class="field-label"> 
     <input class="field-value" 
       [type]="type" 
       [required]="required" 
       (blur)="onBlur()" 
       [(ngModel)]="value" 
       #fieldValue="ngModel"> 
     <span class="field-name">{{ label }}</span> 

    </label> 
    <div class="field-label" *ngIf="disabled"> 
     <span class="field-value">{{ value }}</span> 
     <span class="field-name">{{ label }}</span> 
    </div> 
    `, 
    providers: [ 
     { 
     provide: NG_VALUE_ACCESSOR, 
     useExisting: forwardRef(()=> DataTextInputComponent), 
     multi: true 
     }, 
     { 
     provide: NG_VALIDATORS, 
     useExisting: forwardRef(()=> DataTextInputComponent), 
     multi: true 
     } 
    ] 
    }) 

    export class DataTextInputComponent implements OnChanges, ControlValueAccessor, Validator { 

@Input() public disabled: boolean = false; 
@Input() public label: string; 
@Input() public required: boolean = false; 
@Input() public type: string = 'text'; 
@ViewChild('fieldValue') public fieldValue: FormControl; 

// infrastructure 
public registerOnChange(fn: any) { this.propagateChange = fn; } 
public registerOnTouched(fn: any) { this.propagateTouch = fn; } 

private propagateChange = (_: any) => { }; 
private propagateTouch = (_: any) => { }; 

/** 
* inner value 
*/ 
private innerValue: any = null; 

/** 
* on changes hook 
*/ 
public ngOnChanges(): void { 
    if (this.disabled) { 
     this.propagateChange(this.innerValue); 
    } 
} 

/** 
* input events 
*/ 
public onBlur(): void { 
    this.propagateChange(this.innerValue); 
    this.propagateTouch(true); 
} 

/** 
* value accessor setter and getter 
*/ 
public get value(): any { 
    return this.innerValue; 
}; 

public set value(value: any) { 
    if (value !== 'undefined') { 
     this.innerValue = value; 
     this.propagateChange(value); 
     this.propagateTouch(true); 
    } 
} 

/** 
* value accessor implementation 
* @param value 
*/ 
public writeValue(value: any): void { 
    if (value !== this.innerValue) { 
     this.innerValue = value; 
    } 
} 

/** 
* validation 
* @param c 
*/ 
public validate(c: FormControl) { 
    return this.errors = (this.disabled) ? null : this.customValidate(c); 
} 
private customValidate(c: FormControl): {} { 
    if (c.touched) { 
    // some validation logic which is not relevant here; 
    return null; 
    } 
    return null; 
} 
} 

に使用される他のコンポーネントがあります。フォームも同じです(カラーピッカーとng-selectのように)。

これは奇妙な部分です。フォームの値は正しく設定されています。エラーはありません。値は、データ・テキスト入力コンポーネント内の正しく表示されます(disabled!disabledの両方)、およびフォーム内の他のコンポーネント)。変わった部分は、this.profileFormオブジェクトをデバッガで検査すると、controlsプロパティにはそれぞれの値を持つすべてのコントロールがありますが、disabledプロパティ(別名入力フィールドなし)が設定されているフォームのvalueプロパティはそれらを逃しています本当。ここで

はPlunkerは次のとおりです。https://plnkr.co/edit/nbWQZzQjhGae622CanGa?p=preview

任意のアイデア?

+0

あなたのコードに電子メールコントロールが表示されません。あなたの問題を示すプランナーを作成できますか? – yurzui

+0

私は質問をplunker – pop

+0

に更新しました[コードやエラーの画像を投稿しない](https://meta.stackoverflow.com/q/303812/995714)また、ここでの問題ではなく、将来的に誰も助けない明日に変化したり消えたりすることができるプランナーではありません:[mcve] – Rob

答えて

0

まあ、私はAbstractControl.prototype.updateValueAndValidityまでの値の設定の方法を下にトレースしていると、それはdisabled変数名を使用すると、ここで悪い考えたことが、判明するまで、これは、明らかではなかった。

<form #profileForm="ngForm"> 
    <data-text-input 
      label="lastName" 
      [required]="true" 
      [disabled]="userIsRegistered"      
      name="lastName" 
      ngModel></data-text-input> 
</form> 

私はdisabledプロパティをisReadOnlyに改名しました。なぜなら、readonlyは、他の場所でチェックされる可能性のある属性でもあり、TypeScriptインターフェイスでもあります。

関連する問題