如何将 Object 转换为 Formgroup?

How can I transfrom Object into a Formgroup?

我在将对象转换为表单组时遇到问题。我有我的形式的初始化。我有 surveyData,一个具有相同结构的对象。我想知道如何使我的对象的值转换为 FormGroup

surveyForm: FormGroup;
ngOnInit(): void {
     this.surveyForm = this.formBuilder.group({
       'surveyTitle': new FormControl(null, Validators.required),
       'surveyDescription': new FormControl(null),
       'questionsDetail': this.formBuilder.array([
         this.formBuilder.group({
          'questionType': new FormControl(null, Validators.required),
           'question': new FormControl(null, Validators.required),
           'choices': this.formBuilder.array([])
         })
       ])
     });
     
    };

非常感谢您的帮助。 提前致谢

你有初始数据吗?看起来你会的。您可以使用 angular 模板驱动方法将数据从对象映射到模板中的 ngModel 指令。

<form #form>
 <input type="text" [(ngModel)]="data.surveyTitle" required>
 ...
 <input type="text" [(ngModel)]="data.questionsDetail.choices">
</form>
interface IData {
   surveyTitle: string;
   questionsDetail: {
      ...
      choices: string;
   }
}

@Component({...})
export MyComponent {
   // for the reason if you need an entire form to get a status e.g dirty or access to the entire form data
   // 'form' will be available in 'ngAfterViewInit' hook
   @ViewChild('form', {static: true, read: NgForm})
   form: NgForm
   
   @Input()
   data: IData
}

你需要的是一点递归。当然,如果你不喜欢递归,你总是可以将其转换为迭代,但对我们来说,递归有时更容易理解。

constructor(private fb: FormBuilder) {

  const data = {
      email: 'test@email.com',
      password: 'test-password',
      address: [
        {
          street: 'Street 1',
          postCode: 1000
        },
        {
          street: null,
          postCode: null
        }
      ]
    };

    const validationSchema = {
      email: [[Validators.required, Validators.email]],
      password: [[Validators.required, Validators.minLength(6)]],
      address: [
        {
          street: [[Validators.required]],
          postCode: [[Validators.required]]
        },
        {
          street: [[Validators.required]],
          postCode: [[Validators.required]]
        }
      ]
    };

    this.form = this.parseData(data, validationSchema) as FormGroup;

  }


  parseData(data: any, validators?: any): FormGroup | FormArray | [any, ValidatorFn[], AsyncValidatorFn[]] {
    if (Array.isArray(data)) {
      return this.fb.array(data.map((item, index) => this.parseData(item, (validators || {})[index])));
    }
    if (typeof data === 'object' && data !== null) {
      const formGroupContent = {};
      for (const [key, value] of Object.entries(data)) {
        formGroupContent[key] = this.parseData(value, (validators || {})[key]);
      }
      return this.fb.group(formGroupContent);
    }
    const [syncValidators = [], asyncValidators = []] = validators || [];
    return [data, syncValidators, asyncValidators];
  }

parseData 方法读取数据对象并根据值创建 formArrayformGroupformControl(但使用短语法和数组 - [value,同步验证器、异步验证器])。在这里,我假设您在某个地方为每个单独的表单设置了验证模式,但是如果您使用字符串或其他东西将它们保存在数据对象本身中,您可以创建一个类似的函数,该函数从您从后端接收的模式对象构造验证模式.

我花了一些时间来生成动态表单,当您开始在组件模板内连接不同的表单元素时,有趣的部分就开始了,因为您也必须在那里做类似的事情。根据我的记忆,我为单个表单元素使用了不同的模板,并且我在模板的上下文中传递了父元素,以便能够正确连接所有内容。