Angular 6动态表单问题 [英] Angular 6 Dynamic Forms issue

查看:81
本文介绍了Angular 6动态表单问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试根据官方文档掌握动态表单,但要根据自己的情况.

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


在这里继续这个问题

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


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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆