Многоразовые вложенные подкомпоненты в формах (встроенные компоненты) с проверкой

Допустим, у нас есть адрес и мы хотим повторно использовать его в нескольких формах (например, человек, компания, ...) В Angular все компоненты, поэтому нам, вероятно, следует написать компонент.

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

1. Компонент настраиваемой формы

Что мне в нем не нравится: чрезмерно сложный, внутри подкомпонента все делегированный. При валидации вам понадобится какая-то «внутренняя форма», чтобы валидация работала. Элементы управления формы должны быть определены в родительском элементе, инкапсуляция на самом деле невозможна. Простой пример, см.: https://stackblitz.com/edit/angular-nested-form-custum-component-test

2. Компонент, который имеет два входа: FormGroup и form-submit-state.

Идея взята из https://medium.com/spektrakel-blog/angular2-building-nested-reactive-forms-7978ecd145e4

Намного проще, чем компонент пользовательской формы. Нам нужно предоставить FormGroup, которая построена вне вложенного компонента. Если мы хотим отображать ошибки проверки «onSubmit», нам также необходимо предоставить дочернему компоненту «отправленное состояние» формы. Простой пример, см. https://stackblitz.com/edit/angular-nested-formcomponent-test

Есть комментарии или лучшие идеи по решению проблемы?

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
3
0
1 329
1

Ответы 1

Демо

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

app.component.html

<nested-form-cmp 
     init = "foo" 
     [formSubmitted] = "f.submitted" 
     [grp] = "myForm">
</nested-form-cmp>

AppComponent нужно будет только инициализировать свои собственные данные формы:

export class AppComponent  {

  myForm: FormGroup;

  constructor(private fb: FormBuilder) {
      this.myForm = fb.group({
        name: ['', Validators.required]
      })
  }

  submit(form: NgForm) {
    console.info("Reactive Form submitted: " + form.submitted);
  }
}

вложенный-form.component.html

Вложенный компонент будет отвечать за создание своей собственной вложенной FormGroup и инициализацию ее с помощью валидаторов:

<div [formGroup] = "grp">
  <div formGroupName = "innerGrp">
  <label>
    Inner name:
    <input formControlName = "name2" type = "text" id = "outer"/>   
  </label>
  <span class = "error" *ngIf = "(formSubmitted || grp.get('innerGrp.name2').touched) && grp.get('innerGrp.name2').hasError('required')">
    Inner name is required
  </span>
  </div>
</div>

вложенный-form.component.ts

export class NestedFormComponent implements OnInit{

  // The FormGroup built in the parent
  @Input() public grp: FormGroup;
  @Input() public init: string;

  // Needed, because the FormGroup does not get the forms submitted state
  @Input() public formSubmitted: boolean;
  constructor(private fb: FormBuilder){ 

  }

  ngOnInit() {
    this.grp.setControl('innerGrp', this.fb.group({
      name2: [this.init, Validators.required]
    }))
  }
}

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

dagerber 02.05.2018 12:12

Я думаю, что наличие компонента, который инкапсулирует группу форм, а также любые валидаторы формы, является допустимым вариантом использования. Я мог видеть ценность в наличии компонента «Адрес», который имеет несколько полей и поддерживает передачу модели адреса, что я мог бы повторно использовать его из разных мест.

pixelbits 02.05.2018 20:21

Другие вопросы по теме