我遵循Todd Motto关于动态形式的文章,角度为2(https://toddmotto.com/angular-dynamic-components-forms)。
每件事情都很完美。
但是我有一个项目,为了愉快的项目,我尝试将格式化的数组传递给config,这是数据:
travel = [
{
type: 'input',
label: 'From',
placeholder: 'From',
name: 'from',
},
{
type: 'input',
label: 'To',
placeholder: 'To',
name: 'to'
}
];
travellers = [
{
type: 'input',
label: 'Name',
placeholder: 'name',
name: 'name',
}
]
config = {
travel: [
{
...this.travel
},
{
...this.travel
}
],
travellers: [
{
...this.travellers
}
]
};
这里是动态表单组件的调用:
<dynamic-form [config]="config" (submitted)="formSubmitted($event)"></dynamic-form>
这是动态表单组件:
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { FormGroup, FormArray, FormControl, FormBuilder } from '@angular/forms';
import * as _ from 'lodash';
@Component({
selector: 'builder-form',
templateUrl: './builder-form.component.html',
styleUrls: ['./builder-form.component.css']
})
export class BuilderFormComponent implements OnInit {
@Input()
config: any[] = [];
@Output()
submitted: EventEmitter<any> = new EventEmitter<any>();
form: FormGroup;
objectKeys = Object.keys;
constructor (private fb: FormBuilder) { }
ngOnInit() {
this.form = this.createGroup();
}
createGroup () {
const group = this.fb.group({});
let groupArray = Object.keys(this.config);
let control;
groupArray.forEach((value, i) => {
group.addControl(value, this.fb.array([]));
control = group.controls[value] as FormArray;
_.map(this.config[value], (val, key) => {
// object is the travel { from, to } and the traveller { name }
let object = {}
_.map(val, (v, k) => {
Object.assign(object, {[v.name]: null})
});
control.push(this.fb.group(object, this.fb.control(null)));
});
});
return group;
}
}
我明白了:
FormGroup {
...
controls {
travel: FormArray {
...
controls: [
0: FormGroup {
controls: { form: FormControl, to: FormControl }
},
1: FormGroup {
controls: { form: FormControl, to: FormControl }
}
]
...
},
travellers: FormArray {
...
controls: [
0: FormGroup {
controls: { name: FormControl }
}
]
...
}
}
...
}
这似乎很好。
但我不知道为什么我无法使用form.controls.travel.controls
或form.controls['travel'].controls
访问控件我总是收到错误:'AbstractControl'类型中不存在属性'控件'
在HTML中:
<form class="dynamic-form" [formGroup]="form" (ngSubmit)="submitted.emit(form.value)">
<ng-container *ngFor="let array of objectKeys(config)">
<div [formArrayName]="array">
<ng-container *ngFor="let field of config[array]; let i = index" [formGroupName]="i">
<ng-container dynamicField [config]="field" [group]="form.controls[array].controls[i]"></ng-container>
</ng-container>
</div>
</ng-container>
</form>
但这不起作用......
{{ form.value }}
返回正确的对象:
{
"travel": [
{
"from": null,
"to": null
},
{
"from": null,
"to": null
}
],
"travellers": [
{
"name": null
}
]
}
你是如何使它有效的?
也许错误就在这里:
import { Directive, Input, ComponentFactoryResolver, OnInit, ViewContainerRef } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormButtonComponent, FormInputComponent, FormSelectComponent, FormResetComponent, FormDateComponent, FormNumberComponent } from '../components';
const components = {
button: FormButtonComponent,
input: FormInputComponent
};
@Directive({
selector: '[dynamicField]'
})
export class DynamicFieldDirective implements OnInit {
@Input()
config;
@Input()
group: FormGroup;
component;
constructor (
private resolver: ComponentFactoryResolver,
private container: ViewContainerRef
) {}
ngOnInit () {
const component = components[this.config.type];
const factory = this.resolver.resolveComponentFactory<any>(component);
this.component = this.container.createComponent(factory);
this.component.instance.config = this.config;
this.component.instance.group = this.group;
}
}
BuilderFormComponent.html:12 ERROR Error: No component factory found for undefined. Did you add it to @NgModule.entryComponents?
at noComponentFactoryError (core.es5.js:3202)
at CodegenComponentFactoryResolver.webpackJsonp.../../../core/@angular/core.es5.js.CodegenComponentFactoryResolver.resolveComponentFactory (core.es5.js:3267)
at BuilderFieldDirective.webpackJsonp.../../../../../src/app/builder-form/directives/builder-field.directive.ts.BuilderFieldDirective.ngOnInit (builder-field.directive.ts:35)
at checkAndUpdateDirectiveInline (core.es5.js:10856)
at checkAndUpdateNodeInline (core.es5.js:12357)
at checkAndUpdateNode (core.es5.js:12296)
at debugCheckAndUpdateNode (core.es5.js:13160)
at debugCheckDirectivesFn (core.es5.js:13101)
at Object.eval [as updateDirectives] (BuilderFormComponent.html:13)
at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:13086)
View_BuilderFormComponent_2 @ BuilderFormComponent.html:12
webpackJsonp.../../../core/@angular/core.es5.js.DebugContext_.logError @ core.es5.js:13426
webpackJsonp.../../../core/@angular/core.es5.js.ErrorHandler.handleError @ core.es5.js:1080
(anonymous) @ core.es5.js:4819
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:392
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run @ zone.js:142
webpackJsonp.../../../core/@angular/core.es5.js.NgZone.runOutsideAngular @ core.es5.js:3844
webpackJsonp.../../../core/@angular/core.es5.js.ApplicationRef_.tick @ core.es5.js:4819
webpackJsonp.../../../core/@angular/core.es5.js.ApplicationRef_._loadComponent @ core.es5.js:4787
webpackJsonp.../../../core/@angular/core.es5.js.ApplicationRef_.bootstrap @ core.es5.js:4775
(anonymous) @ core.es5.js:4546
webpackJsonp.../../../core/@angular/core.es5.js.PlatformRef_._moduleDoBootstrap @ core.es5.js:4546
(anonymous) @ core.es5.js:4508
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:392
onInvoke @ core.es5.js:3890
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke @ zone.js:391
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run @ zone.js:142
(anonymous) @ zone.js:844
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:425
onInvokeTask @ core.es5.js:3881
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:192
drainMicroTaskQueue @ zone.js:602
Promise resolved (async)
scheduleMicroTask @ zone.js:585
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.scheduleTask @ zone.js:414
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleTask @ zone.js:236
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.scheduleMicroTask @ zone.js:256
scheduleResolveOrReject @ zone.js:842
ZoneAwarePromise.then @ zone.js:932
webpackJsonp.../../../core/@angular/core.es5.js.PlatformRef_._bootstrapModuleWithZone @ core.es5.js:4537
webpackJsonp.../../../core/@angular/core.es5.js.PlatformRef_.bootstrapModule @ core.es5.js:4522
../../../../../src/main.ts @ main.ts:11
__webpack_require__ @ bootstrap 92732b2f740421148d04:54
0 @ main.bundle.js:1187
__webpack_require__ @ bootstrap 92732b2f740421148d04:54
webpackJsonpCallback @ bootstrap 92732b2f740421148d04:25
(anonymous) @ main.bundle.js:1
BuilderFormComponent.html:12 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 1, nodeDef: {…}, elDef: {…}, elView: {…}}
答案 0 :(得分:0)
@yurzui好吧我的坏,我需要在指令中循环配置... OMG我失去了这么多时间!谢谢你的帮助,这帮助我理解了这个错误。