Angular之表单(三)

所谓好记性不如烂笔头,本博客是基于《Angular权威教程》上的内容学习的记录笔记,这里也推荐大家去看此书,写得挺不错的。同时若有侵权问题,请留言联系,会及时删除相关博客信息。

在Web应用中,表单或许是最重要的一部分。在Angular中,Angular为我们提供了:表单控件(FormControl)封装了表单中的输入,并提供一些可供操纵的对象,验证器(validator)让我们能以自己喜欢的任何方式验证表单输入,观察者(observer)让我们能够监听表单的变化,并作出相应的回应。

一、FormControl和FormGroup

FormControl和FormGroup是Angular中两个基础的表单对象。

FormControl代表单一的输入字段,它是Angular表单中的最小单元。FormControl封装了这些字段的值和状态,比如是否有效、是否脏(被修改过)或是否有错误等。

FormControl的创建方式:

let name = new FormControl("Nate");

大多数表单都拥有不止一个字段,因此我们需要以某种方式来管理多个FormControl。假设我们需要检测表单的有效性,如果要遍历这个FormControl数组并检查每一个FormControl是否有效,必然相当繁琐,而FormGroup则可以提供总包接口(wrapper interface)来解决这个问题。

FormGroup的创建方式:

let personInfo = new FormGroup({
    firstName: new FormControl("Nate");
    lastName: new FormControl("Murray");
    zip: new FormControl("09210");   

});

FormGroup和FormControl都继承自AbstractControl。这意味着检测上述创建的personInfo的状态或值就像检测单个FormControl那么容易。

注意,当我们试图从FormGroup中获取value时,回收到一个“键值对”结构的对象。它能让我们从表单中一次性获取全部的值而不需要单一遍历FormControl。

二、创建我们的第一个表单

创建一个简单的表单:只有一个(带label)输入框和提交按钮。

先把表单变为组件。定义组件需要包含的三部分:

1⃣️配置@Component()注解

2⃣️创建模版

3⃣️在组件定义类中实现自定义功能

为了使用表单,我们需要导入表单库,Angular中有两种使用表单的方式:使用FormsModule和ReactiveFormsModule。我们将这两个库都导入项目中。

在项目的app.ts中导入如下数据:

import { FormsModule, ReactiveFormsModule} from '@angular/forms';

imports: [
                   FormsModule,
                   ReactiveFormsModule
          ],

FormsModule为我们提供了一些模版驱动指令,例如:

1⃣️ngForm

2⃣️ngModel

ReactiveFormsModule则提供了如下指令,例如:

1⃣️formControl

2⃣️ngFormGroup

除此之外还有更多指令,后续逐步介绍

完整的.ts文件如下:

import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule} from '@angular/forms';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { DemoFormSkuComponent } from './demo-form-sku/demo-form-sku.component';

@NgModule({
  declarations: [
    AppComponent,
    DemoFormSkuComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

在HTML文件中定义一个Form表单,代码如下:

<div>
	<h2>Demo Form: Sku</h2>
	<form #f = "ngForm" (ngSubmit) = "onSubmit(f.value)" class="ui form">
		<div class="field">
			<label for="skuinput">SKU</label>
			<input type="text" name="sku" ngModel id="skuinput" placeholder="SKU">
		</div>

		<button type="submit" class="ui button">Submit</button>
	</form>
</div>

(1)form和NgForm

当我们导入FormsModule时,就可以在视图中使用ngForm指令了。记住,当这些指令在视图中使用时,他就会被附加在任何能匹配其selector的节点上。

在使用ngForm指令时,其做了一件便利但隐晦的工作:它的选择器包含form标签(而不是显示添加ngFrom属性)。这意味着当我们导入FromsModule时,ngFrom就会被自带附加到视图中所有的<form>标签上。这确实非常又有,但由于它发生幕后,也许会让许多人感到困惑。

ngForm为我们提供了两个重要的功能:

1⃣️一个名叫ngForm的FormGroup对象

2⃣️一个输出事件(ngSubmit)

在上面例子<form>标签使用了以上两个功能:

<form #f = "ngForm" (ngSubmit) = "onSubmit(f.value)"></form>

说明:我们使用了#f = “ngForm”。#v = thing语法的意思是——在当前视图中创建一个局部变量。这里我们为视图中的ngFrom创建了一个别名,并绑定到变量#f。这个ngForm来自哪里呢?它来自ngFrom指令导出的。

ngForm是什么类型的对象?它是FormGroup类型的对象。这意味着我们可以在视图中把变量f当作FormGroup使用,而这正是输出事件(ngSubmit)中使用方法。

注意:在Angular中NgForm会自动附加到<form>标签上(应为ngForm指令的选择器默认包含了所有的form),这意味着我们可以不必添加ngForm属性就能使用NgForm指令,但是在上述例子中我们依然将ngForm添加到属性的值上。这是为何?

这里需要说明的是:如果ngForm是属性的值,那就是在告述Angular:我们要根据这个属性使用NgForm指令。但在这里,我们需要对一个引用(#f)赋值,因此把ngForm用作属性值。这表示把ngForm这个表达式的执行结果赋值给局部变量f上。既然ngForm在这个节点上,我们可以知道通过ngForm指令导出的这个f变量是FormGroup类型的,接下来就可以在视图的任何地方引用它了。

我们在表单中绑定ngSubmit事件的语法是:(ngSubmit) = "onSubmit(f.value)"。

1⃣️(ngSubmit):来自NgForm指令

2⃣️onSubmit():将会在我们的组件类中进行定义(稍后定义)

3⃣️f.value:f就是前面提到的FormGroup,而.value会以键值对的形式返回FormGroup中的所有控件的值。

总结起来,这行代码的意思是:“当我们提交表单时,将会以该表单的值作为参数,调用组件实例上的onSubmit方法”。

(2)input和NgModel

示例代码:

<input type="text" name="sku" ngModel id="skuinput" placeholder="SKU">

NgModel指令指的是selector是ngModel。这意味着我们可以通过添加这个属性把它附加到input标签上:ngmodel = “whatever”。这里我们指定了一个不带属性值的ngModel。

有两种不同的方法能在模版中指定ngModel,这里使用的是第一种。当使用不带属性值的ngModel时,我们需要指定:

1⃣️单向数据绑定

2⃣️希望在表单中创建一个名为sku的FormControl(这个sku来自input标签的name属性)

NgModel会创建一个新的FormCOntrol对象,把它自身添加到父FormGroup上(这里也就是form表单对象上),并把这个FormControl对象绑定到一个DOM上,也就是说,它会在视图input标签和FormControl对象之间建立关联。这种关联通过name属性建立的,在本例中是“sku”。

注意:NgModel和ngModel有什么不同呢?通常,我们使用Pascal命名法(如NgModel)时,指的是类和供代码中引用的对象。首字母小写的驼峰命名法(如ngModel)来自指令的选择器selector,并且只会被用在DOM/模版中。需要指出的是,NgModel和FormControl并不是同一个。NgModel是用在视图中的指令,而FormControl则用来表示表单中的数据和校验规则。有时我们希望使用ngModel来实现AngularJS那样的双向数据绑定。

现在来看组件类的实现,代码如下:

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

@Component({
  selector: 'app-demo-form-sku',
  templateUrl: './demo-form-sku.component.html',
  styleUrls: ['./demo-form-sku.component.css']
})
export class DemoFormSkuComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  onSubmit(form: any): void {
  	console.log("you submited value:", form);
  }

}

(3)使用FormBuilder(响应式表单)

使用ngForm和ngModel隐式构建FormGroup和FormControl确实很方便,但无法为我们提供更多的定制化选项。使用FormBuilder构建表单则是一种更为灵活和通用的方式。

FormBuilder是一个名副其实的表单构建助手。我们知道表单由FormControl和FormGroup构成,而FormBuilder则可以帮组我们创建它们(你可以把它看作一个“工厂”)。

使用FormBuilder需要导入FormGroup和FormBuilder类。导入代码如下(部分代码未显示):

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';

@Component({
  selector: 'app-demo-form-builder',
  templateUrl: './demo-form-builder.component.html',
  styleUrls: ['./demo-form-builder.component.css']
})

通过在组建上声明带参数的contructor,我们注入了一个FormBuilder。代码如下:

export class DemoFormBuilderComponent implements OnInit {

  myForm: FormGroup;

  constructor(fb: FormBuilder) { 
  	this.myForm = fb.group({
  		'sku': ['ABC123']
  	});
  }

  onSubmit(form: any): void {
  	console.log("you submited value :", form);
  }

  ngOnInit() {
  }

}

我们通过Angular注入一个从FormBuilder类创建的对象实例,并把它赋值给fb变量。FormBuilder中有两个主要函数:

1⃣️control,用于创建一个新的FormControl对象;

2⃣️group,用于创建一个新的FormGroup对象

在上述代码中,myForm是一个FormGroup类型。我们通过调用fb.group()来创建FormGroup。group()方法的参数是代表组内各个FormControl的键值对。

在这里,我们设置了一个名为sku的控件,其值为[“ABC123“]——意思是其默认值为“ABC123”。(你可能注意到这是一个数组。这是因为稍后还会添加更多配置项)。

现在我们能在视图中使用myfForm了。(也就是说,我们需要将它绑定到表单元素上)。

如何在视图中使用myForm呢?我们说过,当我们导入FormModel时,ngForm就会自动添加到<form>标签上。还提到ngForm还会自动创建自己的FormGroup。但我们不希望使用外部的FormGroup,而是使用FormBuilder创建的myForm实例变量。该如何做?

Angualr为我们提供了另外一个指令,能够让我们使用FormBuilder构建的现有FormGroup。指令名称为:formGroup,可以这样使用。代码如下:

<div>
	<h2>Demo Form: Sku</h2>
	<form [formGroup] = "myForm" (ngSubmit) = "onSubmit(myForm.value)" class="ui form">
		<div class="field">
			<label for="skuinput">SKU</label>
			<input type="text" [formControl] = "myForm.controls['sku']" id="skuinput" placeholder="SKU">
		</div>

		<button type="submit" class="ui button">Submit</button>
	</form>
</div>

正如上述代码所示,我们需要把onSubmit中的f替换成myForm,应为现在的myForm变量中保存着表单的配置和值。另外,想要让程序正常执行,还需要做最后一件事:将我们的FormControl绑定到<input>标签上。记住ngControl会创建一个FormControl对象,并附加到父FormGroup中。但在该例子中我们已经使用FormBuilder创建了自己的FormControl。在这里我们将<input>标签上的formControl指令指向myForm.controls上现有的FormControl控件sku即可。

创建表单你需要记住以下两点:

1⃣️如果想要隐式创建新的FormGroup和FormControl,使用:

ngForm

ngModel

2⃣️如果要绑定一个现有的FormGroup和FormControl,使用:

formGroup

formControl

(4)添加验证

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值