Angular 6动态表单问题 [英] Angular 6 Dynamic Forms issue
问题描述
我正在尝试根据官方文档掌握动态表单,但要根据自己的情况.
I'm trying to master dynamic forms following the official documentation but with my own case.
我有一个api,我试图从 https://demo7782009.mockable.io/form中获取数据并在相应的表单字段中将其打印出来. 每个字段都有自己的验证要求.
I have api that I'm trying to fetch data from https://demo7782009.mockable.io/form and print it out in corresponding form fields. Each field has own validation requirements.
但是出现错误
错误:formGroup需要一个FormGroup实例.请传递一个.
Error: formGroup expects a FormGroup instance. Please pass one in.
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
I've tried to make a plunker with my app, but it doesn't bootstrap
所以有我的代码(对此很抱歉)
So there is my code (sorry for that)
App.component.ts
import { FetchFormService } from './fetch-form.service';
import { QuestionControlService } from './question-control.service';
import { Component, OnInit } from '@angular/core';
import { QuestionBase } from './Models/question-base';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
questions: QuestionBase<any>[];
form: FormGroup;
constructor(
private qcs: QuestionControlService,
private ffs: FetchFormService
) {
}
ngOnInit() {
this.ffs.getData().subscribe(data => {
this.questions = data.data;
let formQuestions: [QuestionBase<any>];
this.questions.forEach(e => {
formQuestions.push(new QuestionBase(e));
});
this.form = this.qcs.toFormGroup(formQuestions);
});
}
}
App.component.html
<form [formGroup]="form">
<div *ngFor="let question of questions; let i = index">
<app-question-item [question]="question" [index]='i' [form]="form"></app-question-item>
</div>
<button [disabled]="!form.valid">Submit</button>
</form>
QuestionBase模型
export class QuestionBase<T> {
value: T;
values?: string[];
label: string;
type: string;
constructor(options: {
value: T,
values?: string[],
label: string,
type: string
}) {
this.value = options.value;
this.label = options.label;
this.type = options.type;
this.values = options.values;
}
}
Question-item.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { QuestionBase } from '../Models/question-base';
import { FormGroup } from '@angular/forms';
@Component({
selector: 'app-question-item',
templateUrl: './question-item.component.html',
styleUrls: ['./question-item.component.css']
})
export class QuestionItemComponent implements OnInit {
@Input() question: QuestionBase<any>;
@Input() form: FormGroup;
@Input() index;
constructor() { }
ngOnInit() {
}
}
Question-item.component.html
<div [formGroup]="form">
<label>
{{ question.label }}
<ng-container [ngSwitch]="question.type">
<input [formControlName]="'field' + index" *ngSwitchCase="'string' || 'integer' || 'double'" type="text">
<textarea [formControlName]="'field' + index" *ngSwitchCase="'text'" cols="30" rows="10"></textarea>
<ul *ngSwitchCase="'list'">
<li *ngFor="let item of question.values; let subindex = index">
<input [formControlName]="'field' + index + subindex" type="text">
</li>
</ul>
</ng-container>
</label>
</div>
Fetch-form.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
interface Form {
data: {
type: string,
label: string,
value: string,
values?: string[]
}[];
}
@Injectable({
providedIn: 'root'
})
export class FetchFormService {
constructor(
private http: HttpClient
) { }
getData() {
return this.http.get<Form>('https://demo7782009.mockable.io/form');
}
}
Question-control.service.ts
import { QuestionBase } from './Models/question-base';
import { Injectable } from '@angular/core';
import { FormControl, Validators, FormGroup } from '@angular/forms';
@Injectable({
providedIn: 'root'
})
export class QuestionControlService {
constructor() { }
toFormGroup(questsions: QuestionBase<any>[]) {
let group: any = {};
questsions.forEach((e, i) => {
if (e.type === 'string' || e.type === 'text' || e.type === 'list') {
group[i] = new FormControl(e.value, Validators.required);
} else if (e.type === 'integer') {
group[i] = new FormControl(e.value, [Validators.required, Validators.pattern(/\d+/)]);
} else if (e.type === 'double') {
group[i] = new FormControl(e.value, [Validators.required, Validators.pattern(/\d+\.\d+/)]);
} else {}
});
return new FormGroup(group);
}
}
App.module.ts
import { QuestionItemComponent } from './question-item/question-item.component';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
QuestionItemComponent
],
imports: [
BrowserModule,
ReactiveFormsModule,
HttpClientModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
在这里继续这个问题
Continuation of this questions is here
Angular 6 Dynamic Forms issue [part 2]
推荐答案
您声明要填写表格
form: FormGroup;
但是忘了实例化.您做到了
But forgot to instanciate it. You did this
this.form = this.qcs.toFormGroup(...);
但是您正在等待HTTP调用完成,这意味着在调用完成之前它是未定义的.
But you are waiting for your HTTP call to complete, meaning that it's undefined until the call is done.
考虑对HTML进行调整:
Consider conditioning your HTML :
<form [formGroup]="form" *ngIf="form">
对于沙箱,请考虑使用 http://stackblitz.io
By the way, for sandboxes, consider using http://stackblitz.io
这篇关于Angular 6动态表单问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!