如何将 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 方法读取数据对象并根据值创建 formArray
、formGroup
或 formControl
(但使用短语法和数组 - [value,同步验证器、异步验证器])。在这里,我假设您在某个地方为每个单独的表单设置了验证模式,但是如果您使用字符串或其他东西将它们保存在数据对象本身中,您可以创建一个类似的函数,该函数从您从后端接收的模式对象构造验证模式.
我花了一些时间来生成动态表单,当您开始在组件模板内连接不同的表单元素时,有趣的部分就开始了,因为您也必须在那里做类似的事情。根据我的记忆,我为单个表单元素使用了不同的模板,并且我在模板的上下文中传递了父元素,以便能够正确连接所有内容。
我在将对象转换为表单组时遇到问题。我有我的形式的初始化。我有 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 方法读取数据对象并根据值创建 formArray
、formGroup
或 formControl
(但使用短语法和数组 - [value,同步验证器、异步验证器])。在这里,我假设您在某个地方为每个单独的表单设置了验证模式,但是如果您使用字符串或其他东西将它们保存在数据对象本身中,您可以创建一个类似的函数,该函数从您从后端接收的模式对象构造验证模式.
我花了一些时间来生成动态表单,当您开始在组件模板内连接不同的表单元素时,有趣的部分就开始了,因为您也必须在那里做类似的事情。根据我的记忆,我为单个表单元素使用了不同的模板,并且我在模板的上下文中传递了父元素,以便能够正确连接所有内容。