Подтвердить что ты не робот

Разделение формы на несколько компонентов с проверкой

Я хочу создать одну большую форму с помощью angular 2. Но я хочу создать эту форму с несколькими компонентами, как показано в следующем примере. Компонент приложения

<form novalidate #form1="ngForm" [formGroup]="myForm">
<div>
    <address></address>
</div>
<div>
    <input type="text" ngModel required/>
</div>

<input type="submit" [disabled]="!form1.form.valid" > </form>

Компонент адреса

<div>
<input type="text" ngModel required/> </div>

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

4b9b3361

Ответ 1

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

Есть ли другой простой пример для этого? Может быть, тот же пример без петель

Я могу привести вам пример. Все, что вам нужно сделать, это FormGroup и передать это ребенку.

Допустим, ваша форма выглядит следующим образом, и вы хотите передать address formgroup потомку:

ngOnInit() {
  this.myForm = this.fb.group({
    name: [''],
    address: this.fb.group({ // create nested formgroup to pass to child
      street: [''],
      zip: ['']
    })
  })
}

Затем в родительском элементе просто передайте вложенную группу форм:

<address [address]="myForm.get('address')"></address>

У вашего ребенка используйте @Input для вложенной группы форм:

@Input() address: FormGroup;

И в вашем шаблоне используйте [formGroup]:

<div [formGroup]="address">
  <input formControlName="street">
  <input formControlName="zip">
</div>

Здесь

демонстрация

Более подробная информация здесь о вложенных моделях управляемых форм.

Ответ 2

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

  • Вы можете создать компонент ControlValueAccessor (который принимает атрибут ngModel) со всеми проверками, но затем трудно отображать ошибки проверки и распространять изменения (адрес рассматривается как одно поле формы со сложным значением).
  • Возможно, вы могли передать ссылку на форму в компонент "Адрес" и зарегистрировать в ней свои внутренние элементы управления, но я не пробовал это и, кажется, странный подход (я его нигде не видел).
  • Вы можете переключиться на реактивные формы (вместо управляемых шаблонами), передать объект группы форм (представляющий адрес) в компонент Address, сохраняя проверку в определении вашей формы. Здесь вы можете увидеть пример https://scotch.io/tutorials/how-to-build-nested-model-driven-forms-in-angular-2

Ответ 3

Я хотел бы поделиться подходом, который сделал работу в моем случае. Я создал следующую директиву:

import { Directive } from '@angular/core';
import { ControlContainer, NgForm } from '@angular/forms';

@Directive({
  selector: '[appUseParentForm]',
  providers: [
    {
      provide: ControlContainer,
      useFactory: function (form: NgForm) {
        return form;
      },
      deps: [NgForm]
    }
  ]
})
export class UseParentFormDirective {
}

Теперь, если вы используете эту директиву для дочернего компонента, например:

<address app-use-parent-form></address>

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

Проверено только с Angular 6

Ответ 4

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

@Component({
viewProviders: [{ provide: ControlContainer, useExisting: ngForm}]
}) export class ChildComponent

Вы должны убедиться, что каждый вход имеет уникальное имя. Поэтому, если вы используете * ngFor для вызова дочернего компонента, вы должны поместить индекс (или любой другой уникальный идентификатор) в имя, например:

[name]="'address_' + i"

Если вы хотите структурировать свою форму в FormGroups, вы используете ngModelGroup и

viewProviders: [{ provide: ControlContainer, useExisting: NgModelGroup }]

вместо ngForm и добавьте [ngModelGroup]="yourNameHere" в html некоторых ваших дочерних компонентов, содержащих теги.