Spec-Zone.ru › Angular

Создание формы на основе шаблона

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

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

Формы на основе шаблонов и реактивные формы

Angular поддерживает два подхода к проектированию интерактивных форм. Формы на основе шаблонов позволяют использовать в шаблоне Angular специальные директивы для форм. Реактивные формы предлагают управляемый моделью подход к созданию форм.

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

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

Цели

В этом руководстве вы узнаете, как выполнить следующие задачи:

  • Создать форму Angular с компонентом и шаблоном
  • Использовать ngModel для создания двусторонних привязок данных, позволяющих читать и записывать значения элементов управления вводом
  • Обеспечить визуальную обратную связь с помощью специальных классов CSS, отслеживающих состояние элементов управления
  • Отображать пользователям ошибки проверки и условно разрешать ввод в элементах управления формы в зависимости от состояния формы
  • Обмениваться информацией между элементами HTML с помощью переменных-ссылок шаблона

Создание формы на основе шаблона

Формы на основе шаблонов используют директивы, определенные в FormsModule.

Директивы Описание
NgModel Согласует изменения значения связанного элемента формы с изменениями модели данных, позволяя реагировать на ввод пользователя с помощью проверки ввода и обработки ошибок.
NgForm Создает экземпляр верхнего уровня FormGroup и связывает его с элементом <form> для отслеживания совокупного значения и состояния проверки формы. Как только вы импортируете FormsModule, эта директива по умолчанию становится активной для всех тегов <form>. Добавлять специальный селектор не нужно.
NgModelGroup Создает экземпляр FormGroup и связывает его с элементом DOM.

Обзор шагов

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

  1. Создайте базовую форму.
    • Определите пример модели данных
    • Добавьте необходимые инфраструктурные элементы, например FormsModule
  2. Свяжите элементы управления формы со свойствами данных с помощью директивы ngModel и синтаксиса двусторонней привязки данных.
    • Изучите, как ngModel сообщает о состояниях элементов управления с помощью классов CSS
    • Назовите элементы управления, чтобы сделать их доступными для ngModel
  3. Отслеживайте допустимость ввода и состояние элементов управления с помощью ngModel.
    • Добавьте собственный CSS для визуальной обратной связи о состоянии
    • Показывайте и скрывайте сообщения об ошибках проверки
  4. Реагируйте на событие нажатия встроенной кнопки HTML, добавляя данные в модель.
  5. Обрабатывайте отправку формы с помощью выходного свойства ngSubmit формы.
    • Отключите кнопку Отправить, пока форма не станет допустимой
    • После отправки замените заполненную форму другим содержимым на странице

Создание формы

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

    export class Actor {
      constructor(
        public id: number,
        public name: string,
        public skill: string,
        public studio?: string,
      ) {}
    }
    
  2. Макет и подробности формы определяются в классе ActorFormComponent.

    import {Component} from '@angular/core';
    
    import {Actor} from '../actor';
    import {FormsModule} from '@angular/forms';
    import {JsonPipe} from '@angular/common';
    
    @Component({
      selector: 'app-actor-form',
      templateUrl: './actor-form.component.html',
      imports: [FormsModule, JsonPipe],
    })
    export class ActorFormComponent {
      skills = ['Method Acting', 'Singing', 'Dancing', 'Swordfighting'];
    
      model = new Actor(18, 'Tom Cruise', this.skills[3], 'CW Productions');
    
      submitted = false;
    
      onSubmit() {
        this.submitted = true;
      }
    
    }

    Значение selector компонента "app-actor-form" означает, что эту форму можно добавить в родительский шаблон с помощью тега <app-actor-form>.

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

    const myActress = new Actor(42, 'Marilyn Monroe', 'Singing');
        console.log('My actress is called ' + myActress.name); // "My actress is called Marilyn"

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

  4. Компонент включает функциональность форм, импортируя модуль FormsModule.

    @Component({
      selector: 'app-actor-form',
      templateUrl: './actor-form.component.html',
      imports: [FormsModule, JsonPipe],
    })
    export class ActorFormComponent {
  5. Форма отображается в макете приложения, определенном в шаблоне корневого компонента.

    <app-actor-form />
    

    Исходный шаблон задает макет формы с двумя группами элементов формы и кнопкой отправки. Группы соответствуют двум свойствам модели данных Actor: name и studio. У каждой группы есть метка и поле для ввода пользователем данных.

    • Элемент управления <input> Имя имеет атрибут HTML5 required
    • Элемент управления <input> Студия не имеет его, поскольку studio является необязательным

    К кнопке Отправить применено несколько классов для стилизации. На этом этапе макет формы представляет собой обычный HTML5 без привязок и директив.

  6. В примере формы используются некоторые классы стилей из Twitter Bootstrap: container, form-group, form-control и btn. Чтобы использовать эти стили, таблица стилей приложения импортирует библиотеку.

    @import url('https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css');
  7. Для формы требуется, чтобы навык актера выбирался из предварительно заданного списка skills, который хранится внутри ActorFormComponent. Цикл Angular @for перебирает значения данных, чтобы заполнить элемент <select>.

    <div class="form-group">
            <label for="skill">Skill</label>
            <select class="form-control" id="skill" required>
              @for (skill of skills; track $index) {
                <option [value]="skill">{{ skill }}</option>
              }
            </select>
          </div>

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

Привязка элементов управления вводом к свойствам данных

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

Директива ngModel, объявленная в FormsModule, позволяет связывать элементы управления в форме на основе шаблона со свойствами модели данных. Если добавить директиву с помощью синтаксиса двусторонней привязки данных, [(ngModel)], Angular сможет отслеживать значение элемента управления и взаимодействие с ним пользователя, а также синхронизировать представление с моделью.

  1. Отредактируйте файл шаблона actor-form.component.html.
  2. Найдите тег <input> рядом с меткой Имя.
  3. Добавьте директиву ngModel, используя синтаксис двусторонней привязки данных [(ngModel)]="...".
<input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" />
  TODO: remove this: {{ model.name }}

ПОЛЕЗНО: В этом примере после каждого тега ввода временно добавлено диагностическое выражение интерполяции {{model.name}}, чтобы показывать текущее значение соответствующего свойства данных. Комментарий напоминает, что после проверки работы двусторонней привязки данных эти диагностические строки нужно удалить.

Доступ к общему состоянию формы

После импорта FormsModule в компонент Angular автоматически создал директиву NgForm и прикрепил ее к тегу <form> в шаблоне (поскольку у NgForm есть селектор form, который соответствует элементам <form>).

Чтобы получить доступ к NgForm и общему состоянию формы, объявите переменную-ссылку шаблона.

  1. Отредактируйте файл шаблона actor-form.component.html.

  2. Обновите тег <form>, добавив переменную-ссылку шаблона #actorForm, и задайте ее значение следующим образом.

    <form #actorForm="ngForm">

    Теперь переменная шаблона actorForm ссылается на экземпляр директивы NgForm, управляющей формой в целом.

  3. Запустите приложение.

  4. Начните вводить текст в поле Имя.

    При добавлении и удалении символов вы увидите, как они появляются и исчезают в модели данных.

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

Именование элементов управления

При использовании [(ngModel)] для элемента необходимо определить для него атрибут name. Angular использует заданное имя, чтобы зарегистрировать элемент в директиве NgForm, связанной с родительским элементом <form>.

В примере элементу <input> добавлен атрибут name со значением "name", что логично для имени актера. Подойдет любое уникальное значение, но полезно использовать описательное имя.

  1. Добавьте аналогичные привязки [(ngModel)] и атрибуты name для элементов Студия и Навык.
  2. Теперь можно удалить диагностические сообщения с интерполированными значениями.
  3. Чтобы убедиться, что двусторонняя привязка данных работает для всей модели актера, добавьте в начало шаблона компонента новую текстовую привязку с каналом json, который сериализует данные в строку.

После этих изменений шаблон формы должен выглядеть следующим образом:

{{ model | json }}
      <div class="form-group">
        <label for="name">Name</label>
        <input
          type="text"
          class="form-control"
          id="name"
          required
          [(ngModel)]="model.name"
          name="name"
        />
      </div>

      <div class="form-group">
        <label for="studio">Studio</label>
        <input
          type="text"
          class="form-control"
          id="studio"
          [(ngModel)]="model.studio"
          name="studio"
        />
      </div>

      <div class="form-group">
        <label for="skill">Skill</label>
        <select class="form-control" id="skill" required [(ngModel)]="model.skill" name="skill">
          @for (skill of skills; track $index) {
            <option [value]="skill">{{ skill }}</option>
          }
        </select>
      </div>

Обратите внимание на следующее:

  • У каждого элемента <input> есть свойство id. Оно используется атрибутом for элемента <label>, чтобы связать метку с элементом управления вводом. Это стандартная функция HTML.

  • У каждого элемента <input> также есть обязательное свойство name, которое Angular использует для регистрации элемента управления в форме.

После проверки результатов можно удалить текстовую привязку {{ model | json }}.

Отслеживание состояний формы

После отправки формы Angular применяет класс ng-submitted к элементам form. Этот класс можно использовать, чтобы изменить стиль формы после ее отправки.

Отслеживание состояний элементов управления

Добавление директивы NgModel к элементу управления добавляет к нему имена классов, описывающих его состояние. Эти классы можно использовать, чтобы изменить стиль элемента управления в зависимости от его состояния.

В следующей таблице описаны имена классов, которые Angular применяет в зависимости от состояния элемента управления.

Состояние Класс, если истинно Класс, если ложно
Элемент управления посещен. ng-touched ng-untouched
Значение элемента управления изменено. ng-dirty ng-pristine
Значение элемента управления допустимо. ng-valid ng-invalid

При отправке Angular также применяет класс ng-submitted к элементам form, но не к элементам управления внутри элемента form.

Используйте эти классы CSS, чтобы задать стили элементов управления в зависимости от их состояния.

Наблюдение за состояниями элементов управления

Чтобы посмотреть, как платформа добавляет и удаляет классы, откройте инструменты разработчика браузера и изучите элемент <input>, соответствующий имени актера.

  1. С помощью инструментов разработчика браузера найдите элемент <input>, соответствующий полю ввода Имя. Вы увидите, что у элемента есть несколько классов CSS помимо "form-control".

  2. При первом отображении классы указывают, что значение допустимо, не менялось после инициализации или сброса и что элемент управления не посещался после инициализации или сброса.

    <input class="form-control ng-untouched ng-pristine ng-valid" />;
  3. Выполните следующие действия с полем <input> Имя и проследите, какие классы появляются.

    • Посмотрите, но не касайтесь. Классы указывают, что элемент не затронут, не изменен и имеет допустимое значение.

    • Щелкните поле имени, затем щелкните за его пределами. Элемент управления теперь посещен, и у элемента появился класс ng-touched вместо класса ng-untouched.

    • Добавьте косые черты в конец имени. Теперь элемент затронут и изменен.

    • Удалите имя. Значение станет недопустимым, поэтому класс ng-invalid заменит класс ng-valid.

Создание визуальной обратной связи для состояний

Пара ng-valid/ng-invalid особенно интересна, поскольку при недопустимых значениях важно подать заметный визуальный сигнал. Также нужно помечать обязательные поля.

Обязательные поля и недопустимые данные можно одновременно обозначить цветной полосой слева от поля ввода.

Чтобы изменить внешний вид таким образом, выполните следующие действия.

  1. Добавьте определения для классов CSS ng-*.

  2. Добавьте эти определения классов в новый файл forms.css.

  3. Добавьте новый файл в проект рядом с index.html:

    .ng-valid[required], .ng-valid.required  {
      border-left: 5px solid #42A948; /* green */
    }
    
    .ng-invalid:not(form)  {
      border-left: 5px solid #a94442; /* red */
    }
    
  4. В файле index.html обновите тег <head>, включив в него новую таблицу стилей.

    <link rel="stylesheet" href="assets/forms.css" />

Показ и скрытие сообщений об ошибках проверки

Поле ввода Имя является обязательным, и при его очистке полоса становится красной. Это указывает на проблему, но пользователь не знает, в чем она заключается и что делать. Можно показать полезное сообщение, проверяя состояние элемента управления и реагируя на него.

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

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

  1. Добавление локальной ссылки на элемент ввода

    Дополните тег input переменной-ссылкой шаблона, с помощью которой можно получить доступ к элементу управления Angular поля ввода из шаблона. В примере эта переменная называется #name="ngModel".

    Переменной-ссылке шаблона (#name) присваивается значение "ngModel", поскольку это значение свойства NgModel.exportAs. Это свойство указывает Angular, как связать переменную-ссылку с директивой.

  2. Добавление сообщения об ошибке

    Добавьте элемент <div> с подходящим сообщением об ошибке.

  3. Условное отображение сообщения об ошибке

    Показывайте или скрывайте сообщение, связав свойства элемента управления name со свойством hidden элемента <div> сообщения.

  4. <div [hidden]="name.valid || name.pristine" class="alert alert-danger">
  5. Добавление условного сообщения об ошибке для имени

    Добавьте условное сообщение об ошибке для поля ввода name, как в следующем примере.

    <label for="name">Name</label>
            <input
              type="text"
              class="form-control"
              id="name"
              required
              [(ngModel)]="model.name"
              name="name"
              #name="ngModel"
            />
            <div [hidden]="name.valid || name.pristine" class="alert alert-danger">
              Name is required
            </div>

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

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

Добавление нового актера

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

  1. В нижней части формы добавьте в шаблон элемент <button> с надписью "Новый актер".

  2. В файле компонента добавьте метод создания актера в модель данных актера.

    newActor() {
        this.model = new Actor(42, '', '');
      }
  3. Свяжите событие щелчка кнопки с методом создания актера newActor().

    <button type="button" class="btn btn-default" (click)="newActor()">New Actor</button>
  4. Снова запустите приложение и нажмите кнопку Новый актер.

    Форма очищается, а полосы обязательных полей слева от полей ввода становятся красными, указывая на недопустимые свойства name и skill. Обратите внимание, что сообщения об ошибках скрыты. Это происходит потому, что форма не изменена: вы еще ничего не меняли.

  5. Введите имя и снова нажмите Новый актер.

    Теперь приложение отображает сообщение об ошибке Name is required, поскольку поле ввода больше не находится в исходном состоянии. Форма помнит, что вы ввели имя до нажатия кнопки Новый актер.

  6. Чтобы восстановить исходное состояние элементов управления формы, сбросьте все флаги программно, вызвав метод reset() формы после вызова метода newActor().

    <button type="button" class="btn btn-default" (click)="newActor(); actorForm.reset()">
            New Actor
          </button>

    Теперь при нажатии кнопки Новый актер сбрасывается и форма, и флаги ее элементов управления.

Отправка формы с помощью ngSubmit

Пользователь должен иметь возможность отправить форму после заполнения. Кнопка Отправить в нижней части формы сама по себе ничего не делает, но из-за своего типа (type="submit") она вызывает событие отправки формы.

Чтобы отреагировать на это событие, выполните следующие действия.

  1. Обработка ngOnSubmit

    Свяжите событие ngSubmit формы с методом onSubmit() компонента actor-form.

    <form (ngSubmit)="onSubmit()" #actorForm="ngForm">
  2. Привязка свойства disabled

    Используйте переменную-ссылку шаблона #actorForm, чтобы получить доступ к форме, содержащей кнопку Отправить, и создать привязку события.

    Свяжите свойство формы, указывающее ее общую допустимость, со свойством disabled кнопки Отправить.

    <button type="submit" class="btn btn-success" [disabled]="!actorForm.form.valid">
            Submit
          </button>
  3. Запуск приложения

    Обратите внимание, что кнопка активна, хотя пока она не выполняет полезных действий.

  4. Удаление значения поля «Имя»

    Это нарушает правило "обязательное", поэтому отображается сообщение об ошибке — и, обратите внимание, кнопка Отправить также отключается.

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

Реакция на отправку формы

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

  1. Обертывание формы

    Оберните всю форму в <div> и свяжите его свойство hidden со свойством ActorFormComponent.submitted.

    <div [hidden]="submitted">
        <h1>Actor Form</h1>
        <form (ngSubmit)="onSubmit()" #actorForm="ngForm">
    
        <!-- ... all of the form ... -->
      </form>
    </div>

    Основная форма видна изначально, потому что свойство submitted имеет значение false до отправки формы, как показано в этом фрагменте из ActorFormComponent:

    submitted = false;
    
      onSubmit() {
        this.submitted = true;
      }

    При нажатии кнопки Отправить флаг submitted становится равным true, и форма исчезает.

  2. Добавление состояния отправки

    Чтобы показать другое содержимое, пока форма находится в состоянии отправки, добавьте следующий HTML под новой оберткой <div>.

    <div [hidden]="!submitted">
        <h2>You submitted the following:</h2>
        <div class="row">
          <div class="col-xs-3">Name</div>
          <div class="col-xs-9">{{ model.name }}</div>
        </div>
        <div class="row">
          <div class="col-xs-3">Studio</div>
          <div class="col-xs-9">{{ model.studio }}</div>
        </div>
        <div class="row">
          <div class="col-xs-3">Skill</div>
          <div class="col-xs-9">{{ model.skill }}</div>
        </div>
        <br />
        <button type="button" class="btn btn-primary" (click)="submitted = false">Edit</button>
      </div>

    Этот <div>, отображающий актера только для чтения с привязками интерполяции, появляется только тогда, когда компонент находится в состоянии отправки.

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

  3. Проверка кнопки «Изменить»

    Нажмите кнопку Изменить, чтобы вернуться к редактируемой форме.

Итоги

Форма Angular, рассмотренная на этой странице, использует следующие возможности платформы для поддержки изменения данных, проверки и других функций.

  • Шаблон HTML-формы Angular
  • Класс компонента формы с декоратором @Component
  • Обработка отправки формы путем привязки к свойству события NgForm.ngSubmit
  • Переменные-ссылки шаблона, такие как #actorForm и #name
  • Синтаксис [(ngModel)] для двусторонней привязки данных
  • Использование атрибутов name для проверки и отслеживания изменений элементов формы
  • Свойство valid переменной-ссылки для элементов ввода указывает, допустимо ли значение элемента управления или следует ли показывать сообщения об ошибках
  • Управление активностью кнопки Отправить путем привязки к свойству допустимости NgForm
  • Пользовательские классы CSS, обеспечивающие визуальную обратную связь для недопустимых элементов управления

Ниже приведен код окончательной версии приложения:

import {Component} from '@angular/core';

import {Actor} from '../actor';
import {FormsModule} from '@angular/forms';
import {JsonPipe} from '@angular/common';

@Component({
  selector: 'app-actor-form',
  templateUrl: './actor-form.component.html',
  imports: [FormsModule, JsonPipe],
})
export class ActorFormComponent {
  skills = ['Method Acting', 'Singing', 'Dancing', 'Swordfighting'];

  model = new Actor(18, 'Tom Cruise', this.skills[3], 'CW Productions');

  submitted = false;

  onSubmit() {
    this.submitted = true;
  }

  newActor() {
    this.model = new Actor(42, '', '');
  }
}
<div class="container">
  <div [hidden]="submitted">
    <h1>Actor Form</h1>
    <form (ngSubmit)="onSubmit()" #actorForm="ngForm">
      <div class="form-group">
        <label for="name">Name</label>
        <input
          type="text"
          class="form-control"
          id="name"
          required
          [(ngModel)]="model.name"
          name="name"
          #name="ngModel"
        />
        <div [hidden]="name.valid || name.pristine" class="alert alert-danger">
          Name is required
        </div>
      </div>

      <div class="form-group">
        <label for="studio">Studio Affiliation</label>
        <input
          type="text"
          class="form-control"
          id="studio"
          [(ngModel)]="model.studio"
          name="studio"
        />
      </div>

      <div class="form-group">
        <label for="skill">Skill</label>
        <select
          class="form-control"
          id="skill"
          required
          [(ngModel)]="model.skill"
          name="skill"
          #skill="ngModel"
        >
          @for (skill of skills; track $index) {
            <option [value]="skill">{{ skill }}</option>
          }
        </select>
        <div [hidden]="skill.valid || skill.pristine" class="alert alert-danger">
          skill is required
        </div>
      </div>

      <button type="submit" class="btn btn-success" [disabled]="!actorForm.form.valid">
        Submit
      </button>
      <button type="button" class="btn btn-default" (click)="newActor(); actorForm.reset()">
        New Actor
      </button>
    </form>
  </div>

  <div [hidden]="!submitted">
    <h2>You submitted the following:</h2>
    <div class="row">
      <div class="col-xs-3">Name</div>
      <div class="col-xs-9">{{ model.name }}</div>
    </div>
    <div class="row">
      <div class="col-xs-3">Studio</div>
      <div class="col-xs-9">{{ model.studio }}</div>
    </div>
    <div class="row">
      <div class="col-xs-3">Skill</div>
      <div class="col-xs-9">{{ model.skill }}</div>
    </div>
    <br />
    <button type="button" class="btn btn-primary" (click)="submitted = false">Edit</button>
  </div>
</div>
export class Actor {
  constructor(
    public id: number,
    public name: string,
    public skill: string,
    public studio?: string,
  ) {}
}
<app-actor-form />
import {Component} from '@angular/core';
import {ActorFormComponent} from './actor-form/actor-form.component';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  imports: [ActorFormComponent],
})
export class AppComponent {}
import {bootstrapApplication} from '@angular/platform-browser';
import {AppComponent} from './app/app.component';
import {provideZoneChangeDetection} from '@angular/core';

bootstrapApplication(AppComponent, {
  providers: [provideZoneChangeDetection({eventCoalescing: true})],
}).catch((err) => console.error(err));
.ng-valid[required], .ng-valid.required  {
  border-left: 5px solid #42A948; /* green */
}

.ng-invalid:not(form)  {
  border-left: 5px solid #a94442; /* red */
}

Super-powered by Google ©2010–2025.
Code licensed under an MIT-style License. Documentation licensed under CC BY 4.0.
https://angular.dev/guide/forms/template-driven-forms

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API