角6个动态表单问题(Angular 6 Dynamic Forms issue)

2019-10-30 12:32发布

我试图掌握的官方文档以下,但我自己的情况下,动态表单。

我有我试图从获取数据API https://demo7782009.mockable.io/form ,并打印出来在相应的表单字段。 每个领域都有自己的验证要求。

但收到一个错误

错误:formGroup期望一个FormGroup实例。 请把1英寸

  Example: <div [formGroup]="myGroup"> <input formControlName="firstName"> </div> In your class: this.myGroup = new FormGroup({ firstName: new FormControl() }); 

我试图做一个plunker与我的应用程序,但它并没有引导

所以我的代码(对不起,那)

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;
  }
}

问题-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() {
  }

}

问题-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>

取-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');
  }
}

问题-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 { }

这个问题的延续,是这里

角度6动态表单问题[第2部分]

Answer 1:

你宣布你形成

form: FormGroup;

但忘了实例化它。 你这样做

this.form = this.qcs.toFormGroup(...);

但是,你正在等待你的HTTP调用来完成,这意味着直到调用完成它的定义。

考虑调理你的HTML:

<form [formGroup]="form" *ngIf="form">

顺便说一句,对于沙箱,可以考虑使用http://stackblitz.io



Answer 2:

你的错误是很常见的,它没有任何关系的动态形式。 当你初始化你的组件,HTML模板被加载。 在此之前,你ngOnInit被触发,但它仍然在等待来自后端的响应。 为此你的“形式”变量是不确定的。 因为你的模板被加载[formGroup]="undefined"你得到这个错误。

<form [formGroup]="form" *ngIf="form">

该ngIf解决了这个问题,因为这将确保您的表单模板是不是想加载你肯定在创建formgroup之前。



文章来源: Angular 6 Dynamic Forms issue