Разделение реактивной формы на несколько компонентов с проверкой - PullRequest
0 голосов
/ 06 мая 2020

Можем ли мы разделить реактивную форму на несколько компонентов?.

Например, кнопки (СОХРАНИТЬ, ОБНОВИТЬ и УДАЛИТЬ) в родительском компоненте, а форма помещается в дочерний компонент.

Как этого добиться?

есть ли примеры?

Спасибо

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

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

@Injectable()
export class MyFormService {
  private _form: FormGroup;
  constructor(private fb: FormBuilder) {
    this.buildForm()
  }

  private buildForm() {
    this._form = this.fb.group({
      // whatever form specifics in here
    })
  }

  get form() {
    return this._form
  }

  // whatever of these you need
  get childForm() {
    return this.form.get('childFormKey')
  }

  // any other appropriate methods or observables exposed
}

родительский компонент:

@Component({
  .. component stuff ..
  providers: [MyFormService] // might as well provide it here to keep it private
})
export class ParentComponent {
  constructor(private formService: MyFormService) {

  }

  onSubmit() {
    const value = this.formService.form.value;
    // do the submit
  }
  // any methods you need

}

дочерний

export class ChildComponent {
  childForm: FormGroup

  constructor(private formService: MyFormService) {
    this.childForm = this.formService.childForm;
    // do whatever else you need for this component
  }
}

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

Для вещей, которые больше похожи на «виджеты» и которые вы собираетесь использовать во многих формах, вероятно, потребуется другой метод.

0 голосов
/ 06 мая 2020

Вы можете разделить реактивную форму на несколько подформ, но вам нужно использовать ControlValueAccessor и его друга, и вам нужно вложить его в родительскую форму, откуда вы ее отправляете. И, конечно же, вам нужно добавить дополнительный шаблон, чтобы иметь всю валидацию и все остальное, что требуется для реактивных форм.

Таким образом вы можете иметь столько подформ, сколько захотите.

Ниже вы можете увидеть пример того, как вы можете сделать это способом Angular:

Дочерний компонент

import { Component, OnInit, forwardRef } from '@angular/core';
import {
  NG_VALUE_ACCESSOR,
  NG_VALIDATORS,
  ControlValueAccessor,
  Validator,
  FormGroup,
  FormBuilder,
  AbstractControl,
  ValidationErrors,
  Validators
} from '@angular/forms';

@Component({
  ...
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ChildComponent),
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => ChildComponent),
      multi: true
    }
  ]
})
export class ChildComponent implements OnInit, ControlValueAccessor, Validator {
  public childForm: FormGroup;
  public onTouched: () => void = () => {};

  constructor(private fb: FormBuilder) {}

  ngOnInit(): void {
    this.childForm = this.fb.group({
     ...
    });
  }

  public writeValue(val: any): void {
    return val && this.childForm.setValue(val, { emitEvent: false });
  }

  public registerOnChange(fn: any): void {
    this.childForm.valueChanges.subscribe(fn);
  }

  public registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  public setDisabledState?(isDisabled: boolean): void {
    isDisabled ? this.childForm.disable() : this.childForm.enable();
  }

  public validate(control: AbstractControl): ValidationErrors | null {
    return this.childForm.valid
      ? null
      : { invalidForm: { valid: false, message: 'Form is invalid' } };
  }
}

Шаблон дочернего компонента:

<ng-container [formGroup]="childForm">
.....
</ng-container>

Родительский компонент ts

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

@Component({
  ...
})
export class StandardSetupFormComponent implements OnInit {
  parentForm: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit(): void {
    this.parentForm = this.fb.group({
      child: null,
      ...
    });
  }

 public onSubmit() {
  ...
 }
}

Шаблон родительского компонента:

<form class="form" [formGroup]="parentForm" (ngSubmit)="onSubmit()">

  <app-child formControlName="child"></app-child>

  <button[disabled]="parentForm.invalid">Submit</button>
</form>

Как вы можете видеть в родительском компоненте, вам нужно рассматривать дочернюю форму как элемент управления.

Есть и другие способы сделать это. Например, используя входные данные, и даже если это выглядит проще, это неправильный путь.

Я прочитал отличную статью о том, что показывал вам выше go, но я не могу пока не найду. Я обновлю ответ, если сделаю это.

Здесь - это статья, которая даст вам лучшее и более глубокое понимание вложенности реактивных форм.

...