【问题标题】:Angular 2. Rebuild form control(s)Angular 2. 重建表单控件
【发布时间】:2017-10-20 20:21:15
【问题描述】:

有没有办法强制 Angular 表单重新创建它的控件?我的意思是创建新实例?看起来它只在初始加载时创建它们。不确定我是否真的需要它,但这是我的问题:

我有一个“编辑”控件,其中包含我需要编辑的项目的@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([]) 之前被调用。

我可以在writeValue 中使用setTimeout(() =&gt; this.updateValue()),这似乎有帮助,但我不喜欢这个解决方案。如何在表单绑定之前进行控件属性绑定?在initForm() 之前调用超时或强制 Angular 检测更改不起作用。

【问题讨论】:

    标签: angular typescript angular-forms


    【解决方案1】:

    我做类似事情的方式是在 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 设置器中调用它。

    【讨论】:

    • 谢谢。这似乎对我不起作用,我没有使用 fb.array (它有什么魔力吗?)但试图将我的项目移动到表单控件并绑定到它。未检测到更改。我让它工作的唯一方法是引用下拉菜单并直接将其设置为items 属性。然后它立即发生在表单数据绑定之前。
    猜你喜欢
    • 2020-09-30
    • 2016-09-18
    • 2017-02-21
    • 2017-03-31
    • 2016-08-09
    • 2018-02-21
    • 2017-07-03
    • 2018-06-04
    • 2017-03-02
    相关资源
    最近更新 更多