Как динамически добавлять дополнительные элементы управления формой через шаблон?

Итак, у меня проблема в том, что у меня есть базовый компонент, имеющий форму. Но я хотел бы иметь возможность добавить к нему еще одно поле. Почему? Потому что у меня есть четыре страницы с очень похожей структурой, которые отличаются максимум одним полем. У меня есть stackblitz, который тоже должен донести идею. Часть рендеринга работает хорошо и хорошо.

Но чтобы дать общее представление:

@Component({
  selector: 'app-base-form',
  standalone: true,
  imports: [ReactiveFormsModule, CommonModule],
  template: `<form
  style = "display: flex; flex-direction: column; gap: 1rem"
  [formGroup] = "form"
>
  <input formControlName = "search" type = "text" placeholder = "Search something" />

  <ng-template
    [ngTemplateOutletContext] = "{ $implicit: form }"
    [ngTemplateOutlet] = "seachOptionalField()!"
  ></ng-template>
</form>`,
})
export class BaseFormComponent {
  seachOptionalField = input<TemplateRef<any>>();
  fb = inject(UntypedFormBuilder);
  form = this.fb.group({
    search: this.fb.control(['']),
  });
}

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

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, BaseFormComponent],
  template: `
    <app-base-form [seachOptionalField] = "searchOptionalField"></app-base-form>
    <ng-template #searchOptionalField let-form>
    <input type = "text" placeholder = "We just added this" />
    {{form.value | json}}
    </ng-template>
  `,
})
export class App {}
Тестирование функциональных 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
0
0
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо указать соответствующий formControlName для новых элементов управления, а также обернуть их в элемент формы внутри шаблона.

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

Рабочий пример ниже со stackblitz!

Полный код:

main.ts

import { Component, inject } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import 'zone.js';
import { BaseFormComponent } from './app/base-form/base-form.component';
import { ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, BaseFormComponent, ReactiveFormsModule],
  template: `
    <app-base-form [seachOptionalField] = "searchOptionalField" [extraFormParams] = "extraFormParams"></app-base-form>
    <ng-template #searchOptionalField let-form>
      <form [formGroup] = "form">
        <input type = "text" placeholder = "We just added this" formControlName = "search2"/>
    </form>
    {{form.value | json}}
    </ng-template>
  `,
})
export class App {
  fb = inject(UntypedFormBuilder);
  extraFormParams = {
    search2: this.fb.control(['']),
  };
}

bootstrapApplication(App);

базовая форма.ts

import { CommonModule } from '@angular/common';
import { Component, TemplateRef, inject, input } from '@angular/core';
import {
  FormGroup,
  ReactiveFormsModule,
  UntypedFormBuilder,
} from '@angular/forms';

@Component({
  selector: 'app-base-form',
  standalone: true,
  imports: [ReactiveFormsModule, CommonModule],
  template: `<form
  style = "display: flex; flex-direction: column; gap: 1rem"
  [formGroup] = "form"
>
  <input formControlName = "search" type = "text" placeholder = "Search something" />

  <ng-template
    [ngTemplateOutletContext] = "{ $implicit: form }"
    [ngTemplateOutlet] = "seachOptionalField()!"
  ></ng-template>
</form>`,
})
export class BaseFormComponent {
  seachOptionalField = input<TemplateRef<any>>();
  extraFormParams = input<Object>({});
  fb = inject(UntypedFormBuilder);
  form!: FormGroup;

  ngOnInit() {
    this.form = this.fb.group({
      search: this.fb.control(['']),
      ...this.extraFormParams(),
    });
  }
}

Демо-версия Stackblitz

Проклятие! У меня была идея использовать там тег формы, но идея предоставить элементы управления в качестве входных данных просто никогда не приходила мне в голову! Иногда простые решения оказываются лучшими! Большое спасибо!

ak.leimrey 17.04.2024 13:28

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