2017-10-20 15 views
0

角度フォームにコントロールを再作成させる方法はありますか?私は新しいインスタンスを作成することを意味しますか?初期ロード時にのみ作成されるように見えます。私が本当にそれが必要かどうかわからないが、私の問題はここにある:角2.フォームコントロールを再構築

私は編集する必要がある項目の@Input() set item(editItem)を持っている "編集"コントロールを持っています。私は親からこの項目を設定し、コントロールはフォームの値をリセットする必要があります。 フォームの中には、オプションのバインド可能なリストを持つ独自のカスタムドロップダウンコントロールを使用します。

一般的に、それは次のようになります。

@Component({ 
    template:` 
    <form [formGroup]="form"> 
     <my-control [items]="items" formControlName="itemId"></app-combobox> 
    </form> 
    ` 

export class EditComponent implements OnInit { 
    items = [{text: 'Item 1', itemId: 1}, {text: 'Item 2', itemId: 2}]; 

    @Input() set editItem(item) { 
    //if some logic... 
     this.items = [{text: 'Item 3', itemId: 3}, {text: 'Item 4', itemId: 4}]; 

    this.initForm(item); 
    } 

    constructor(private _fb: FormBuilder) {} 

    ngOnInit(): void { 
    this.initForm(); 
    } 

    initForm(item?) { 
    this.form = this._fb.group({ 
     // itemId could differ and should be in the items list before binding happens 
     'itemId': [item ? item.itemId : null] 
    } 
} 

と制御:

export class ComboboxComponent implements ControlValueAccessor { 
    items = []; 

    @Input() set items(list[]) { 
    this.items = list; 
    this.updateValue(); 
    } 

    // ControlValueAccessor implementation 
    writeValue(value: any) { 
    this.updateValue(); 
    } 

    updateValue() { 
    // here we try to use a newly updated list (but it's not updated yet!) 
    } 
} 

そして問題は、私は、フォームが結合新しいformGroupを作成する前に、項目の新しいリストを設定する場合でも発生していることですアイテムリストのバインディングの前にControlValueAccessorインターフェイスのwriteValueメソッドが、ドロップダウンコントロールの@Input() set items([])の前に呼び出されます。

setTimeout(() => this.updateValue())writeValueの中に使用できますが、私はこの解決策が嫌いです。フォームバインディングの前に制御プロパティーのバインディングを行うにはどうすればよいですか? initForm()の前にタイムアウトを呼び出したり、Angularに変更を検出させたりすることはできません。

答えて

0

私は似たようなやり方では、このようなngOnInit何かにフォーム構造を設定することです:

ngOnInit(): void { 
    this.productForm = this.fb.group({ 
     productName: ['', [Validators.required, 
          Validators.minLength(3), 
          Validators.maxLength(50)]], 
     productCode: ['', Validators.required], 
     starRating: ['', NumberValidators.range(1, 5)], 
     tags: this.fb.array([]), 
     description: '' 
    }); 

そして私は、データ変更時ということを変更しないでください。むしろ、フォームの値を次のようなコードで更新するだけです。

onProductRetrieved(product: IProduct): void { 
    if (this.productForm) { 
     this.productForm.reset(); 
    } 
    this.product = product; 

    // Update the data on the form 
    this.productForm.patchValue({ 
     productName: this.product.productName, 
     productCode: this.product.productCode, 
     starRating: this.product.starRating, 
     description: this.product.description 
    }); 
    this.productForm.setControl('tags', this.fb.array(this.product.tags || [])); 
} 

これは@Inputセッターから呼び出すことができます。

+0

ありがとうございます。私はfb.arrayを使用していませんでした(それはどんな魔法をしますか?)しかし、フォームコントロールにアイテムを移動してバインドしようとしました。変更は検出されません。 私が動作させる唯一の方法は、子としてドロップダウンを参照し、 'items'プロパティを直接設定することです。その後、フォームデータバインディングの直前に発生します。 – rook