带有父子路由的部分反应式表单

时间:2019-05-25 05:48:22

标签: angular angular-routing angular-reactive-forms

我是新手。我们正在尝试使用Angular反应性表单

来构建大型表单 此示例的

PFA stackblitz链接。我有一个父级组件person-form及其两个子级组件person-job和person-info,每个组件中都包含几个字段。

我有两个无法解决的困难。

1)我希望用户完全填写父表格,然后在最后提交。但是,如果我先填写信息详细信息,然后再填写工作详细信息表格,然后再返回信息;信息中的详细信息不存在。如何使用反应式表单方法将填写的详细信息保留在表单中。这是在子窗体导航上发生的。

2)其次,我想将两种形式的结果合并为一个json并将其发送到父形式组件,即person-form。如何实现这一目标。我现在可以得到

 {title: "XYZ", salary: "0000"} 
 // and
 {name: "ABC", age: "12"}

但是我想要这样的东西:

 { 
  combinedForm : {
     info:{name: "ABC", age: "12"},
     job:{title: "XYZ", salary: "0000"}
    }
 } 

 // OR

 {
  combinedForm : {
     name: "ABC", age: "12",title: "XYZ", salary: "0000"
   }
 }

这样我就可以轻松地一次从服务器发送或接收数据。

MyStackblitz

2 个答案:

答案 0 :(得分:0)

如果您对使用路由实现此目标不满意,则可以选择几种方法。

在开始讨论之前,您可能会发现只使用制表符机制而不进行路由会更容易。

这里最简单的解决方案是在组件之间共享表单的共享服务。

制作如下表格服务:

@Injectable()
export class PersonFormService {
  private _form: FormGroup;
  get form() {
    return this._form;
  }
  constructor(private fb: FormBuilder) {
    this._form = this.fb.group({
      title: ['',Validators.required],
      salary:['',Validators.required],
      name: ['',Validators.required],
      age:['']});
  }
}

然后在您的父级提供此表单服务:

@Component({
  selector: 'app-person-form',
  templateUrl: './person-form.component.html',
  styleUrls: ['./person-form.component.css'],
  providers: [PersonFormService]
})

然后在您的组件中使用表格:

export class PersonJobComponent implements OnInit {

  constructor(private personFormService:PersonFormService) { }

  formJob:FormGroup;
  ngOnInit() {
    this.formJob= this.personFormService.form;
  }

  submit(){
    console.log(this.formJob.value);

  }
}

export class PersonInfoComponent implements OnInit {


  constructor(private personFormService: PersonFormService) { }

  form:FormGroup;
  ngOnInit() {
    this.form=this.personFormService.form;
  } 

}

现在,您将在两个组件中都拥有整个表单。

有效的堆叠闪电战:https://stackblitz.com/edit/angular-qrym5k

如果要出于验证目的或其他目的而分别对待这两个子表单,只需将服务中的表单结构重构为2个表单组。

类似:

@Injectable()
export class PersonFormService {
  private _form: FormGroup;

  get combinedForm() {
    return this._form;
  }

  get jobForm() {
    return this._form.get('job') as FormGroup;
  }

  get infoForm() {
    return this._form.get('info') as FormGroup;
  }

  constructor(private fb: FormBuilder) {
    this._form = this.fb.group({
      info: this.fb.group({
        name: ['',Validators.required],
        age:['']
      }),
      job: this.fb.group({
        title: ['',Validators.required],
        salary:['',Validators.required]
      })
    });
  }
}

然后只需在各自的组件中适当使用personFormService.infoForm或.jobForm。

答案 1 :(得分:0)

您可以使用服务在两个或多个组件之间共享表单数据。您可以使用服务名称PersonFormService。服务将是这样的:

import { Injectable } from '@angular/core';

@Injectable()
export class PersonFormService {
  personForm: PersonForm;
  constructor() {
    this.personForm = new PersonForm();
  }

  set infoDetails(info) {
    this.personForm.info = info;
  }

  set jobDetails(job) {
    this.personForm.job = job;
  }

  get infoDetails() {
    return this.personForm.info;
  }

  get jobDetails() {
    return this.personForm.job;
  }
}

export class PersonForm {
  info: any;
  job: any;

  constructor() {
    this.job = {};
    this.info = {};
  }
}

现在在这两个组件中,您都可以使用以下服务:

person-job.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { FormGroup } from '@angular/forms';
import { Validators } from '@angular/forms';
import { PersonFormService } from '../../person-form.service';
@Component({
  selector: 'app-person-job',
  templateUrl: './person-job.component.html',
  styleUrls: ['./person-job.component.css']
})
export class PersonJobComponent implements OnInit {

  constructor(private fb: FormBuilder, private formService: PersonFormService) { }

  formJob:FormGroup;
  completeForm: any;
  ngOnInit() {
    this.formJob=this.fb.group({
      title: ['',Validators.required],
      salary:['',Validators.required]});

    this.formJob.patchValue(this.formService.jobDetails);
  }
  submit(){
    console.log(this.formJob.value);
    this.formService.jobDetails = this.formJob.value;
  }
}

person-info.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { FormGroup } from '@angular/forms';
import { Validators } from '@angular/forms';
import { PersonFormService } from '../../person-form.service';
@Component({
  selector: 'app-person-info',
  templateUrl: './person-info.component.html',
  styleUrls: ['./person-info.component.css']
})
export class PersonInfoComponent implements OnInit {


  constructor(private fb: FormBuilder, private formService: PersonFormService) { }

  form:FormGroup;
  ngOnInit() {
    this.form=this.fb.group({
      name: ['',Validators.required],
      age:['']});

    this.form.patchValue(this.formService.infoDetails);
  }

  submitForm() {
    console.log("submit")
   this.formService.infoDetails = this.form.value; 
  } 

}

现在要解决您的第二个问题,您可以使用spread运算符将两个表单合并为一个表单。您的代码将如下所示:

this.completeForm = {...this.formService.infoDetails, ...this.formService.jobDetails }

查看完整的 stackblitz 演示here