Формы Angular 2

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

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

Далее мы шаг за шагом реализуем функциональность формы.


Создание проекта

Импортируйте начальный проект.

Для полного создания проекта обратитесь к:Настройка среды TypeScript в Angular 2

Или скачайте исходный код напрямую:Нажмите здесь, чтобы скачать

После распаковки переименуйте каталог в angular-forms и измените следующее в файле angular-forms/package.json:"name": "angular-quickstart"на"name": "angular-forms"。

Когда все готово, мы запускаемcnpm install, чтобы загрузить пакеты зависимостей.

Создание модели Site

Приведенный ниже код создает простой класс модели Site, содержащий три обязательных поля: id, name, url, и одно необязательное поле: alexa.

Создайте файл site.ts в каталоге angular-forms/app со следующим кодом:

Файл app/site.ts:

export class Site { constructor( public id: number, public name: string, public url: string, public alexa?: number ) { } }

В приведенном ниже коде поля, помеченные как public, являются публичными полями, а знак вопроса (?), добавленный после alexa, указывает на необязательное поле.

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

Каждая форма Angular состоит из двух частей: шаблона на основе HTML и компонента на основе кода, который обрабатывает данные и взаимодействие с пользователем.

Создайте файл site-form.component.ts в каталоге angular-forms/app со следующим кодом:

Файл app/site-form.component.ts:

import { Component } from '@angular/core'; import { Site } from './site'; @Component({ moduleId: module.id, selector: 'site-form', templateUrl: 'site-form.component.html' }) export class SiteFormComponent { urls = ['www.example.com', 'www.google.com', 'www.taobao.com', 'www.facebook.com']; model = new Site(1, 'Example', this.urls[0], 10000); submitted = false; onSubmit() { this.submitted = true; } //TODO: Удалить после завершения get diagnostic() { return JSON.stringify(this.model); } }

В примере импортируются декоратор Component и модель Site.

Селектор @Component "site-form" означает, что можно использовать тег<site-form>, чтобы вставить эту форму в родительский шаблон.

Свойство templateUrl указывает на отдельный HTML-файл шаблона с именем site-form.component.html.

Свойство diagnostic используется для возврата JSON-представления этой модели.

Определите корневой модуль приложения

Измените app.module.ts, чтобы определить корневой модуль приложения, который задает внешние ссылки и объявляет компоненты, принадлежащие этому модулю, например SiteFormComponent.

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

Код файла app/app.module.ts выглядит следующим образом:

Файл app/app.module.ts:

import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { SiteFormComponent } from './site-form.component'; @NgModule({ imports: [ BrowserModule, FormsModule ], declarations: [ AppComponent, SiteFormComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }

Создать корневой компонент

Измените файл корневого компонента app.component.ts, чтобы разместить в нем SiteFormComponent.

Файл app/app.component.ts:

import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: '<site-form></site-form>' }) export class AppComponent { }

Создать начальный HTML-шаблон формы

Создайте файл шаблона site-form.component.html с кодом, как показано ниже:

файл app/site-form.component.html:

<div class="container"> <h1>Форма сайта</h1> <form> <div class="form-group"> <label for="name">Название сайта</label> <input type="text" class="form-control" id="name" required> </div> <div class="form-group"> <label for="alexa">Рейтинг Alexa</label> <input type="text" class="form-control" id="alexa"> </div> <button type="submit" class="btn btn-default">Отправить</button> </form> </div>

Атрибут required делает поле обязательным; если он не задан, поле необязательно.

Введите следующую команду в каталоге angular-forms:

cnpm install bootstrap --save

Откройте файл index.html и добавьте следующие ссылки на стили в <head>:

<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">

Запуститеnpm startЗатем посетите: http://localhost:3000/, вывод будет следующим:


Используйте ngModel для двусторонней привязки данных

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

Измените app/site-form.component.html, чтобы привязать нашу форму к модели с помощью ngModel. Код показан ниже:

файл app/site-form.component.html:

<div class="container"> <h1>Форма сайта</h1> <форма> {{diagnostic}} <div class="form-group"> <label for="name">Название сайта</label> <input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name"> </div> <div class="form-group"> <label for="alexa">Рейтинг Alexa</label> <input type="text" class="form-control" id="alexa" [(ngModel)]="model.alexa" name="alexa"> </div> <div class="form-group"> <label for="url">URL веб-сайта</label> <select class="form-control" id="url" required [(ngModel)]="model.url" name="url"> <option *ngFor="let p of urls" [value]="p">{{p}}</option> </select> </div> <button type="submit" class="btn btn-default">Отправить</button> </form> </div>
  • Каждый элемент input имеет атрибут id, который используется атрибутом for элемента label для сопоставления метки с соответствующим input.

  • Каждый элемент input имеет атрибут name, который нужен модулю forms Angular, чтобы зарегистрировать элемент управления для формы.

Запустите приведённый выше пример; результат вывода будет следующим:

{{diagnostic}} Он используется только для вывода данных во время тестирования.

Мы также можем использовать ngModel для отслеживания состояния изменений и проверки валидности. Он использует три класса CSS для обновления элементов управления, чтобы отразить текущее состояние.

State Класс при значении true Класс, когда false
Элемент управления был посещён ng-touched ng-untouched
Значение элемента управления изменилось ng-dirty ng-pristine
Значение элемента управления корректно ng-valid ng-invalid

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

Создайте файл forms.css в каталоге angular-forms. Код выглядит следующим образом:

Файл forms.css:

.ng-valid[required], .ng-valid.required { border-left: 5px solid #4276A9; /* green */ } .ng-invalid:not(form) { border-left: 5px solid #a94442; /* red */ }

Откройте файл index.html и добавьте следующие ссылки на стили в <head>:

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

Измените app/site-form.component.html. Ниже показан код:

файл app/site-form.component.html:

<div class="container"> <h1>Форма сайта</h1> <форма> {{diagnostic}} <div class="form-group"> <label for="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">Имя веб-сайта обязательно</div> </div> <div class="form-group"> <label for="alexa">Рейтинг Alexa</label> <input type="text" class="form-control" id="alexa" [(ngModel)]="model.alexa" name="alexa"> </div> <div class="form-group"> <label for="url">URL веб-сайта</label> <select class="form-control" id="url" required [(ngModel)]="model.url" name="url"> <option *ngFor="let p of urls" [value]="p">{{p}}</option> </select> </div> <button type="submit" class="btn btn-default">Отправить</button> </form> </div>

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

Удалите данные из поля name, и отображаемый результат будет следующим:

Добавить веб-сайт

Далее мы создаём форму для добавления веб-сайта. Добавьте кнопку в app/site-form.component.html:

файл app/site-form.component.html:

<button type="button" class="btn btn-default" (click)="newSite()">Добавить веб-сайт</button>

Привяжите событие вышеуказанной кнопки к методу компонента:

Файл app/site-form.component.ts:

active = true; newSite() { this.model = new Site(5, '', ''); this.active = false; setTimeout(() => this.active = true, 0); }

Мы добавляем флаг active в компонент и инициализируем его значением true. Когда мы добавляем новый сайт, он устанавливает флаг active в false, а затем быстро возвращает его в true с помощью быстрой функции setTimeout.

Отправка формы через ngSubmit

Мы можем использовать директиву NgSubmit из Angular для отправки формы и привязать её к методу SiteFormComponent.submit() через механизм привязки событий.

<form *ngIf="active" (ngSubmit)="onSubmit()" #siteForm="ngForm">

Мы определили ссылочную переменную шаблона #siteForm и инициализировали её значением "ngForm".

Эта переменная siteForm теперь ссылается на директиву NgForm, которая представляет форму в целом.

Полный код файла site-form.component.ts выглядит следующим образом:

Файл app/site-form.component.ts:

import { Component } from '@angular/core'; import { Site } from './site'; @Component({ moduleId: module.id, selector: 'site-form', templateUrl: 'site-form.component.html' }) export class SiteFormComponent { urls = ['www.example.com', 'www.google.com', 'www.taobao.com', 'www.facebook.com']; model = new Site(1, 'Пример руководства', this.urls[0], 10000); submitted = false; onSubmit() { this.submitted = true; } //TODO: удалить после завершения get diagnostic() { return JSON.stringify(this.model); } active = true; newSite() { this.model = new Site(5, '', ''); this.active = false; setTimeout(() => this.active = true, 0); } }

app/site-form.component.html полный код выглядит следующим образом:

файл app/site-form.component.html:

<div class="container"> <div [hidden]="submitted"> <h1>Форма веб-сайта</h1> <form *ngIf="active" (ngSubmit)="onSubmit()" #siteForm="ngForm"> {{diagnostic}} <div class="form-group"> <label for="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">Имя веб-сайта обязательно</div> </div> <div class="form-group"> <label for="alexa">Рейтинг Alexa</label> <input type="text" class="form-control" id="alexa" [(ngModel)]="model.alexa" name="alexa"> </div> <div class="form-group"> <label for="url">URL веб-сайта</label> <select class="form-control" id="url" required [(ngModel)]="model.url" name="url"> <option *ngFor="let p of urls" [value]="p">{{p}}</option> </select> </div> <button type="submit" class="btn btn-default" [disabled]="!siteForm.form.valid">Отправить</button> <button type="button" class="btn btn-default" (click)="newSite()">Добавить веб-сайт</button> </form> </div> <div [hidden]="!submitted"> <h2>Информация, которую вы отправили, выглядит следующим образом:</h2> <div class="row"> <div class="col-xs-3">Название сайта</div> <div class="col-xs-9 pull-left">{{ model.name }}</div> </div> <div class="row"> <div class="col-xs-3">Рейтинг сайта Alexa</div> <div class="col-xs-9 pull-left">{{ model.alexa }}</div> </div> <div class="row"> <div class="col-xs-3">URL сайта</div> <div class="col-xs-9 pull-left">{{ model.url }}</div> </div> <br> <button class="btn btn-default" (Нажмите)="submitted=false">Редактировать</button> </div> </div>

В шаблоне мы привязываем атрибут hidden к свойству SiteFormComponent.submitted.

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

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

Итоговая структура каталогов:

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

Скачать исходный код

Полный пример демонстрации в GIF выглядит следующим образом:

Другие расширения