2017-10-20 158 views
0

有没有办法强制Angular窗体重新创建它的控件?我的意思是创建新的实例?看起来它只是在初始加载时创建它们。不知道是否真的需要它,但这是我的问题:Angular 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形式结合发生之前设定的项目的一个新的列表在我的物品清单绑定之前。在我的下拉控件上,在@Input() set items([])之前调用ControlValueAccessor接口的writeValue方法。

我可以使用setTimeout(() => this.updateValue())里面的writeValue它似乎有帮助,但我不喜欢这种解决方案。我怎样才能使控件属性绑定发生在表单绑定之前?调用超时或强制Angular在initForm()不起作用之前检测到更改。

回答

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 setter调用它。

+0

谢谢。这对我来说似乎没有任何作用,要么我没有使用fb.array(它有没有什么魔法?),但试图将我的物品移动到窗体控件并绑定到它。未检测到更改。 我让它工作的唯一方法是将下拉菜单作为一个孩子引用,并直接设置它为'items'属性。然后,它立即发生,并形成数据绑定。 – rook