简介
Angel提供了两种处理表单的方式:模板驱动表单和反应型表单(也称为模型驱动表单)。模板驱动的表单是以角度处理表单的默认方式。对于模板驱动的表单,模板指令用于构建表单的内部表示形式。使用反应式窗体,您可以在Component类中构建自己的窗体表示形式。
<$>[备注] 注: 反应形式是以角2引入的。 <$>
以下是反应形式的一些优点:
- 使用自定义validators
- 动态更改验证
- 动态添加表单域
在本文中,您将探索如何将反应式应用于一个示例角度应用程序。
前提条件
如果你想跟随这篇文章,你将需要:
- 本地安装node.js,可按照如何安装node.js并创建本地开发Environment.
这篇文章假设你对角度有一些基本的了解。
这篇文章还假设你是从一个新的角度项目构建的,这个项目是由@angular/cli
生成的。您可以参考此post,如果您是角度CLI的入门。
本教程通过了Node v15.1.0、npm
v6.14.8、@angular/core
v11.0.0、@angular/forms
v11.0.0验证。
第一步-设置项目
出于本教程的目的,您将从一个使用@angular/cli
生成的默认角度项目进行构建。
1npx @angular/cli new angular-reactive-forms-example --style=css --routing=false --skip-tests
这将配置一个新的角度项目,将样式设置为),不布线,并跳过测试。
导航到新创建的项目目录:
1cd angular-reactive-forms-example
要使用反应式表单,您将使用Reactive FormsModule
而不是FormsModule
。
在您的代码编辑器中打开app.mode.ts
,添加Reactive FormsModule
:
1[label src/app/app.module.ts]
2import { BrowserModule } from '@angular/platform-browser';
3import { NgModule } from '@angular/core';
4import { ReactiveFormsModule } from '@angular/forms';
5
6import { AppComponent } from './app.component';
7
8@NgModule({
9 declarations: [
10 AppComponent
11 ],
12 imports: [
13 BrowserModule,
14 ReactiveFormsModule,
15 ],
16 providers: [],
17 bootstrap: [AppComponent]
18})
19export class AppModule { }
此时,您应该有了一个带有Reactive FormsModule
的新角度投影。
第二步-在组件模板中添加表单
对于反应式形式,逻辑完全在Component类中声明。
在代码编辑器中打开app.Component.html
并添加以下代码行:
1[label src/app/app.component.html]
2<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
3 <div>
4 <label>
5 Name:
6 <input formControlName="name" placeholder="Your name">
7 </label>
8 </div>
9 <div>
10 <label>
11 Email:
12 <input formControlName="email" placeholder="Your email">
13 </label>
14 </div>
15 <div>
16 <label>
17 Message:
18 <input formControlName="message" placeholder="Your message">
19 </label>
20 </div>
21 <button type="submit">Send</button>
22</form>
这段代码将创建一个包含三个字段的表单:name
、email
和Message
。还将有一个标签为)
方法。
<$>[备注]
注意: 如果您使用的是ANGLE 2.x,还需要加上以form
开头的novaliate
指令,因为ANGLE覆盖HTML5‘S验证。角度为4+时,会在后台自动添加novaliate
。
<$>
让我们来分解一下:
formGroup
:表单在Component类中将被视为FormGroup
,因此formGroup
指令允许为表单组命名。ngSubmit
:表单提交时会触发的事件。formControlName
:每个表单字段都应该有一个formControlName
指令,该指令的值将是Component类中使用的名称。
此时,您应该有了一个新的角度项目,其中包含一个使用形状的构件样板。
第三步-构建组件类
接下来,在Component类中,您将在FormGroup
中定义FormGroup
和单独的`FormControl。
如果提供了一个值When_Newing_aFormControl
,它将被用作该字段的初始值。
注意FormGroup
和FormControl
名称是如何与模板中使用的名称相同的。还要注意如何在ngOnInit
生命周期hook:]中初始化FormGroup
1[label src/app/app.component.ts]
2import { Component, OnInit } from '@angular/core';
3import { FormControl, FormGroup } from '@angular/forms';
4
5@Component({
6 selector: 'app-root',
7 templateUrl: './app.component.html',
8 styleUrls: ['./app.component.css']
9})
10export class AppComponent implements OnInit {
11 myForm: FormGroup;
12
13 ngOnInit() {
14 this.myForm = new FormGroup({
15 name: new FormControl('Sammy'),
16 email: new FormControl(''),
17 message: new FormControl('')
18 });
19 }
20
21 onSubmit(form: FormGroup) {
22 console.log('Valid?', form.valid); // true or false
23 console.log('Name', form.value.name);
24 console.log('Email', form.value.email);
25 console.log('Message', form.value.message);
26 }
27}
就本教程而言,onSubmit
方法实际上不会将提交的表单值传递给任何外部服务或服务器。它用于显示如何访问表单的有效性和FormControl
值。
此时,您可以编译应用程序并在Web浏览器中打开它。输入name
、email
、Message
的值,然后点击[提交],控制台日志就会显示出来。
第四步-更新组件类使用FormBuilder
可以使用FormBuilder
助手重写ngOnInit
表单结构。这允许您放弃所有_Newing_of表单组和表单控件。
在代码编辑器中重新访问app.Component.ts
,移除FormControl
,并将FormGroup
替换为FormBuilder
:
1[label src/app/app.component.ts]
2import { Component, OnInit } from '@angular/core';
3import { FormBuilder, FormGroup } from '@angular/forms';
4
5@Component({
6 selector: 'app-root',
7 templateUrl: './app.component.html',
8 styleUrls: ['./app.component.css']
9})
10export class AppComponent implements OnInit {
11 myForm: FormGroup;
12
13 constructor(private fb: FormBuilder) {}
14
15 ngOnInit() {
16 this.myForm = this.fb.group({
17 name: 'Sammy',
18 email: '',
19 message: ''
20 });
21 }
22
23 onSubmit(form: FormGroup) {
24 console.log('Valid?', form.valid); // true or false
25 console.log('Name', form.value.name);
26 console.log('Email', form.value.email);
27 console.log('Message', form.value.message);
28 }
29}
这段带有FormBuilder
的代码减少了用于创建FormGroup
的样板代码量。
第五步-更新组件类使用Validators
将Validators
类添加到您的导入中,并使用数组而不是简单的字符串值来声明表单控件。
数组中的第一个值是初始表单值,第二个值供验证器使用。请注意如何通过将多个验证器包装到一个数组中来在同一个表单控件上使用它们。
RevisitReview您的代码编辑器中的app.Component.ts
并添加Validators
:
1[label src/app/app.component.ts]
2import { Component, OnInit } from '@angular/core';
3import { FormBuilder, FormGroup, Validators } from '@angular/forms';
4
5@Component({
6 selector: 'app-root',
7 templateUrl: './app.component.html',
8 styleUrls: ['./app.component.css']
9})
10export class AppComponent implements OnInit {
11 myForm: FormGroup;
12
13 constructor(private fb: FormBuilder) {}
14
15 ngOnInit() {
16 this.myForm = this.fb.group({
17 name: ['Sammy', Validators.required],
18 email: ['', [Validators.required, Validators.email]],
19 message: ['', [Validators.required, Validators.minLength(15)]],
20 });
21 }
22
23 onSubmit(form: FormGroup) {
24 console.log('Valid?', form.valid); // true or false
25 console.log('Name', form.value.name);
26 console.log('Email', form.value.email);
27 console.log('Message', form.value.message);
28 }
29}
此代码在name
、email
和Message
字段中添加required d
。它还确保email
值使用有效的电子邮件地址格式。它还确保Message
值至少为15个字符。
如果这些表单要求中有任何一项未通过,则valid
值将为False
。如果所有这些表单要求都通过,则valid
值将为true
。
Step 6-获取模板中的表单值和有效性
在模板中,可以访问每个FormControl
的值和有效性,以及整个表单组的值和有效性。
如果表单值无效,请重新访问app.Component.html
,并使用* ngIf
向用户显示反馈消息:
1[label src/app/app.component.html]
2<form [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)">
3 <div>
4 <label>
5 Name:
6 <input formControlName="name" placeholder="Your name">
7 </label>
8 <div *ngIf="myForm.get('name').invalid && (myForm.get('name').dirty || myForm.get('name').touched)">
9 Please provide a name.
10 </div>
11 </div>
12 <div>
13 <label>
14 Email:
15 <input formControlName="email" placeholder="Your email">
16 </label>
17 <div *ngIf="myForm.get('email').invalid && (myForm.get('email').dirty || myForm.get('email').touched)">
18 Please provide a valid email address.
19 </div>
20 </div>
21 <div>
22 <label>
23 Message:
24 <input formControlName="message" placeholder="Your message">
25 </label>
26 <div *ngIf="myForm.get('message').invalid && (myForm.get('message').dirty || myForm.get('message').touched)">
27 Messages must be at least 15 characters long.
28 </div>
29 </div>
30 <button type="submit" [disabled]="myForm.invalid">Send</button>
31</form>
这段代码检查用户是否与字段(dirty
或Touched
)进行了交互。然后,如果该值没有通过验证要求,它将显示错误消息。在解决表单值的所有问题之前,发送 按钮也将被禁用。
有多种方法可以检索表单控件值。本例使用myForm.get(‘name’)
,相当于myForm.control s.name
。可以使用.hasError(‘Required’)
或.errors.quired
来检索错误信息。
结论
在本文中,您探索了如何将反应式应用于一个示例角度应用程序。您使用FormControl
、FormGroup
、FormBuilder
和Validators
构建了一个带验证的示例表单。有关其他功能,请参考官方documentation.
如果您想了解更多有关ANGLE的信息,请查看我们的ANGLE主题页面以获取练习和编程项目。