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

Теперь, как веб-разработчик, я то и дело натыкаюсь на задачи по созданию форм. С одной стороны, я хочу иметь возможность быстро выполнить эту задачу, а с другой - я хочу, чтобы мои конечные пользователи без проблем работали. Но с постоянно меняющимися требованиями клиентов я также хочу иметь возможность масштабировать простую форму с двумя полями до чего-то большого, скажем, формы приема на работу - с различными подформами для сбора личных, профессиональных и образовательных данных кандидата. Я также не хочу продолжать добавлять, обновлять или удалять из моего шаблона HTML каждый раз, когда есть изменение требований. Как мне сесть и решить, как лучше всего разработать такую ​​форму?

Реактивные формы на помощь

Я уверен, что если вы работали с Angular в прошлом, вы должны знать об этой замечательной функции, предоставляемой Angular прямо из коробки - Реактивные формы. Они очень гибкие, настраиваемые, тестируемые… и все такое - правда. Но я хочу показать вам, как мы можем использовать реальную силу FormGroups и FormControls и использовать их в наших интересах.

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

Перво-наперво. Что нам нужно?

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

Нам нужен волшебный ReactiveFormsModule вместе с FormsModule в нашем app.module.ts (или в вашем функциональном модуле).

Теперь давайте подумаем, как мы продолжим разработку собственно компонента формы. Я делаю это простым и называю это MultiStepFormComponent. Поскольку я хочу, чтобы эта форма была масштабируемой, я создам ее, передав ей объект конфигурации. Это звучит так -

1. Создайте объект конфигурации, который содержит параметры поля ввода, такие как: type, formControlName, заполнитель и т. Д.

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

3. Как только мы закончим писать код, который фактически будет выполнять все вышеперечисленное, мы перейдем к созданию HTML-шаблона для нашей формы. Он должен иметь кнопки для перехода к предыдущей или следующей форме, а также сообщения об ошибках, соответствующие определенным полям формы. Мы можем оставить кнопку отправить как часть этапа предварительного просмотра и отправки, где мы, наконец, сделаем запрос POST с данными, объединенными из всех форм.

Одна вещь, которую мы должны помнить, заключается в том, что вся наша конфигурация находится в этом объекте, назовем его STEP_ITEMS - все, от типа ввода до проверок, которые должны иметь вводимые данные, до сообщений об ошибках, которые вы хотите отображать при недопустимом вводе. ВСЕ! Цель состоит в том, чтобы сохранять конфигурацию отдельно и легко изменять или обновлять.

Шаг 1. Создайте объект конфигурации

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

Ключи каждого объекта будут содержать formControlName ,, который соединит наши поля формы с соответствующими formGroups, и мы увидим волшебство.

Продолжаем… давайте сейчас создадим MultiStepFormComponent. Я тоже хочу создать канал, который будет форматировать ключи в моем объекте конфигурации как таковые:

dateOfBirth ›› Дата рождения

Я называю это, FormatTitlePipe . Теперь мой app.module.ts выглядит так:

Шаг 2. Создайте компонент MultiStepFormComponent

Позвольте мне вкратце осветить каждый строительный блок нашего компонента:

ngOnInit ()

  • Здесь мы укажем activeStepIndex, чтобы мы могли перенаправить пользователя на конкретный шаг, если мы хотим добавить функции сохранить как черновик и возобновить.
  • У нас будет currentFormContent, который просто содержит данные каждого шага. Это будет иметь конфигурацию для каждой формы.
  • У нас будет masterForm, который мы хотим хранить в различных формах, как массив из FormGroup. Мы будем перебирать этот массив в шаблоне HTML, чтобы сгенерировать необходимое количество форм.
  • У нас будет formFields, который, по нашему желанию, будет содержать ключевые строки каждого объекта формы конфигурации в виде массива массивов строк. Мы будем перебирать этот массив для создания обязательных полей формы для каждой формы.

buildForm () и getValidators ()

Здесь я использую службу FormBuilder для создания FormGroups с предварительно определенными FormControls и Validators. Как вы можете ясно видеть, метод buildForm вместе с getValidators выполняет эту задачу, чтобы в конечном итоге вернуть ключ как таковой:

otp: [‘’, [Validators.required, Validators.minLength (4)]]

Если мы хотим использовать один валидатор в каждом поле, мы можем просто передать его как единый объект. Однако здесь я использую массив валидаторов, даже если они нам не нужны. Это упрощает мою работу как разработчика, поскольку я могу использовать любой синтаксис, предоставляемый Angular. Не стесняйтесь инициализировать эти FormControl в соответствии с ожидаемыми типами данных.

getValidationMessage ()

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

goToStep () и setFormPreview ()

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

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

Шаг 3: Приближение к финишу с шаблоном MultiStepFormComponent

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

Здесь важно отметить, что для каждой формы требуется связанный с ней formGroup, чтобы поля формы с атрибутом formControlName были связаны с ней. Это поможет нам отмечать форму на каждом этапе как НЕДЕЙСТВИТЕЛЬНУЮ, если какое-либо из ее полей недействительно.

Следовательно, я отключил кнопку следующий, если пользователь находится на последнем шаге или форма, в которой он / она сейчас находится, НЕВЕРНА. Помимо отключения кнопки next, я написал тег <p>, который появится, как только связанное с ним поле будет затронуто или загрязнено и будет содержать ошибку. Вы можете дополнительно улучшить это, чтобы создать этот тег сообщения об ошибке <p> только для полей, которые настроены с любыми проверками (через объект конфигурации).

Заключение с заключительными словами

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

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

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

Https://stackblitz.com/edit/angular-multi-step-reactive-form?embed=1&file=src/app/constants/multi-step-form.ts