Как повторно использовать FormGroup для заполнения одного и того же поля в разных формах в Angular 9?

#angular #forms #crud #formgroups

#angular #формы #crud #formgroups

Вопрос:

Я создаю форму для сбора данных из поля ввода в Angular.

Допустим, у меня есть (студент, преподаватель, администрация), который заполняет форму.

Они (2 или все) разделяют некоторые поля (день рождения, имя, фамилия), которые можно использовать повторно, и другие поля, которые различны для всех (рабочий адрес, домашний адрес, почтовый адрес) и отличаются только для 2 (идентификатор студента, идентификатор факультета).

Возможно ли иметь несколько групп форм для этой цели? Как бы я подошел к этому, если у каждого из них много полей?

Ответ №1:

Этого можно достичь с помощью реактивных форм на основе моделей с использованием интуитивно понятной библиотеки @rxweb / reactive-form-validators, которую я нашел в npm

npm i @rxweb/reactive-form-validators

Начните с создания класса модели, имеющего свойства, которые вам нужны в вашей formgroup, как показано ниже

 import {  prop, } from "@rxweb/reactive-form-validators"
export class User {

    @prop()
    firstName: string;

    @prop()
    lastName: string;

    @prop()
    emailAddress: string;

}
  

@prop() определяет свойство, которое можно использовать для инициализации FormControl с использованием formGroup метода RxFormBuilder . Эта модель может быть позже в других компонентах, чтобы повторно использовать эти свойства и создавать FormGroup, не записывая один и тот же код несколько раз

 import { Component, OnInit } from '@angular/core';
import { FormGroup } from "@angular/forms"

import { RxFormBuilder } from '@rxweb/reactive-form-validators';

import { User } from './user.model';

@Component({
    selector: 'app-user-add',
    templateUrl: './user-add.component.html'
})
export class UserAddComponent implements OnInit {

    userFormGroup: FormGroup

    constructor(
        private formBuilder: RxFormBuilder
    ) { }

    ngOnInit() {
        let user = new User();
        this.userFormGroup = this.formBuilder.formGroup(user);
    }
}

  

Компонентный HTML-файл выглядит следующим образом:

 <form *ngIf="userFormGroup" [formGroup]="userFormGroup">
  <div class="form-group">
    <label>FirstName</label>
    <input type="text" formControlName="firstName" class="form-control" />
  </div>
  <div class="form-group">
    <label>LastName</label>
    <input type="text" formControlName="lastName" class="form-control" />
  </div>
  <div class="form-group">
    <label>Email Address</label>
    <input type="text" formControlName="emailAddress" class="form-control" />
  </div>
  <button [disabled]="!userFormGroup.valid" class="btn btn-primary">
    Submit
  </button>
</form>

  

Вот полный пример на stackblitz

Если вы хотите расширить класс и добавить дополнительные свойства в FormGroup, вы можете использовать функцию абстракции класса, доступную в той же библиотеке, наряду с этим она поставляется со многими встроенными средствами проверки, что упрощает выполнение проверок

Чтобы узнать больше об этом подходе, пожалуйста, обратитесь к Упрощенным реактивным формам

Ответ №2:

Если вы используете реактивные формы, это может показаться заманчивым, но это довольно просто, когда вы понимаете, что FormGroup это всего лишь объект JS. Из-за этого вы можете использовать их как любой другой объект JS.

Более простым способом было бы реализовать метод, который делает это в сервисе, и использовать ваши знания объектов JS / TS:

 private commonFields;
private roleBasedFields;
private addressForm;

constructor() {
  this.commonFields = {
    firstName: '',
    lastName: ['', Validators.required],
    birthday: [null, Validators.required]
  };

  this.addressForm = {
     street: '',
     streetNo: null,
     zip: null,
     city: '',
     // and so on...
  };

  this.roleBasedFields = {
    student: {
      homeAddress: addressForm,
      // add other fields related to student here
    },
    faculty: {
      workAddress: addressForm,
      // add other fields here
    },
    administration: {
      mailingAddress: {
        ...addressForm,
        department: ['', Validators.required]
        // if the address object is different for a certain role, you can add them like this
      },
      // add other fields here
    },
};

}

buildForm(role: 'student' | 'faculty' | 'administration'): FormGroup {
  return new FormGroup({
    ...this.commonFields,
    ...this.roleBasedFields[role]
  });
}
  

И в компоненте, в зависимости от того, как вы хотите его реализовать, используйте его как:

 someForm: FormGroup;
formArray: FormArray;

ngOnInit() {
  this.someForm = this.thatServiceAbove.buildForm('student');

  // if it goes in an array
  this.formArray = new FormArray([]);
}

// method to push the FormGroup in a FormArray:
generateForm(role: 'student' | 'faculty' | 'administration') {
   this.formArray.push(this.thatServiceAbove.buildForm(role));
}
  

Вы поняли идею: D