How to patch form value to a recursive nested Angular Form?

后端 未结 1 402
死守一世寂寞
死守一世寂寞 2021-01-28 22:58

Recently, I asked the following question on StackOverflow and received an amazing response that resulted in building a recursive nested Angular Form: Angular Deeply Nested React

相关标签:
1条回答
  • 2021-01-28 23:26

    Stackblitz demo

    There's nothing wrong with your data. It's likely a matter of timing. The form must be stable before you can patch any value. As you're doing it in OnInit, I suppose you're building the form in the constructor. If so, the form isn't ready to receive any values yet.

    The simplest way to solve that is with an uncomfortable setTimeout. But I suppose that this is just for testing. In real cases, the data will probably get some time to be available anyway.

    Your example above will work if you wrap it with the aforementioned setTimeout:

    ngOnInit() {
      setTimeout(() => {
        const data = {
          statement: {
            groups: [
              {
                conjunctor: "and",
                conditions: [
                  {
                    variable: "asdf"
                  }
                ],
                groups: []
              }
            ]
          }
        };
        this._form.patchValue(data);
        console.log(this._form.value);
      }, 50);
    }
    

    The animated gif below shows a patch in 3 nested groups, the last one being nested on the second one.

    Building the form according to given data

    One interesting thing you can do is build the form automatically according to the data you have. You can achieve that by analyzing the data that gets into the ControlValueAccessor.writeValue:

    if (!value) {
      return;
    }
    setTimeout(() => {
      if (value && value.conditions && value.conditions.length) {
        this._conditionsFormArray.clear();
        value.conditions.forEach(c => this._addCondition());
      }
    
      if (value && value.groups && value.groups.length) {
        this._groupsFormArray.clear();
        value.groups.forEach(g => this._addGroup());
      }
    
      this._form.patchValue(value);
    }, 50);
    

    Maybe you've noticed the setTimeout above, it's there because we have another setTimeout in the form creation method (called on OnInit) that add a condition to the form after it's created, and the creation of the condition is, itself, inside a setTimeout. Because of that, we must wait it runs, otherwise this._conditionsFormArray.clear(); wouldn't have any effect => no condition would've been created when it runs.

    private _createFormGroup() {
      this._form = this._fb.group({
        conjunctor: null,
        conditions: this._fb.array([]),
        groups: this._fb.array([])
      });
    
      // add one condition on the next tick, after the form creation
      setTimeout(() => this._addCondition());
    }
    

    Then with some adjustments, we can get to the following result (the gif below is based on this other Stackblitz demo):

    0 讨论(0)
提交回复
热议问题