欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Angular表单解析

程序员文章站 2022-04-14 08:55:03
angular中表单分为两种,一种是是模板驱动表,一种是响应式表单。以下分别对模板驱动表单,响应式表单的使用,表单的验证做示例。 1. 模板驱动型表单 1.1模板表单的使用 要使用模板驱动行表单首先...

angular中表单分为两种,一种是是模板驱动表,一种是响应式表单。以下分别对模板驱动表单,响应式表单的使用,表单的验证做示例。

1. 模板驱动型表单

1.1模板表单的使用

要使用模板驱动行表单首先需要在根模块下面引入formsmodule,然后将formsmodule模块导入到根模块的ngmodule中的imports数组中,这样才能够就能访问模板驱动表单的所有特性,包括 ngmodel

模块的引用

import { browsermodule } from '@angular/platform-browser';
import { ngmodule } from '@angular/core';
import { formsmodule } from '@angular/forms';
import { reactiveformsmodule } from '@angular/forms';
import { routes, routermodule } from '@angular/router';

import { appcomponent } from './app.component';
import { logincomponent } from './login/login.component';
import { reactiveformcomponent } from './reactive-form/reactive-form.component';
import { heroformcomponent } from './hero-form/hero-form.component';
import { righsterformcomponent } from './righster-form/righster-form.component';
const routes: routes = [
  {
    path: 'heroform',
    component: heroformcomponent
  },
  {
    path: 'loginform',
    component: logincomponent
  },
  {
    path: 'reactiveform',
    component: reactiveformcomponent
  },
  {
    path: 'registerform',
    component: righsterformcomponent
  },
  {
    path: '',
    redirectto: 'heroform',
    pathmatch: 'full'
  }
];

@ngmodule({
  declarations: [
    appcomponent,
    logincomponent,
    reactiveformcomponent,
    heroformcomponent,
    righsterformcomponent
  ],
  imports: [
    browsermodule,
    formsmodule,
    reactiveformsmodule,
    routermodule.forroot(routes)
  ],
  providers: [],
  bootstrap: [appcomponent]
})
export class appmodule { }

1.2模板表单的详细介绍

新建一个login用来写一个注册的模板表单

其中模板为


{{ myform.value | json }}

ngform:angular 会在

标签上自动创建并附加一个 ngform 指令。

ngform 指令为 form 增补了一些额外特性。 它会控制那些带有 ngmodel 指令和 name 属性的元素,监听他们的属性(包括其有效性)。 它还有自己的 valid 属性,这个属性只有在它包含的每个控件都有效时才是真。

myform是一个模板变量

ngmodel用于双向绑定,如上面的代码表单元素需要设置name属性,也可以写成另一种形式


ngmodelgroup可以用来分组

ngsubmit表单提交事件

myform.value可以获取表单数据。

在表单中使用 ngmodel 可以获得比仅使用双向数据绑定更多的控制权。它还会告诉你很多信息:用户碰过此控件吗?它的值变化了吗?数据变得无效了吗?

ngmodel 指令不仅仅跟踪状态。它还使用特定的 angular css 类来更新控件,以反映当前状态。 可以利用这些 css 类来修改控件的外观,显示或隐藏消息。

状态 为真时的 css 类 为假时的 css 类
控件被访问过。 ng-touched ng-untouched
控件的值变化了。 ng-dirty ng-pristine
控件的值有效。 ng-valid ng-invalid

2. 响应式表单

2.1响应式表单简介

响应式表单使用显式的、不可变的方式,管理表单在特定的时间点上的状态。对表单状态的每一次变更都会返回一个新的状态,这样可以在变化时维护模型的整体性。响应式表单是围绕 observable 的流构建的,表单的输入和值都是通过这些输入值组成的流来提供的,同时,也赋予你对数据进行同步访问的能力。这种方式允许你的模板利用这些表单的“状态变更流”,而不必依赖它们。

响应式表单与模板驱动的表单有着显著的不同点。响应式表单通过对数据模型的同步访问提供了更多的可预测性,使用 observable 的操作符提供了不可变性,并且通过 observable 流提供了变化追踪功能。

2.2 响应式表单具体使用

要使用响应式表单,首先需要在@angular/forms包中导入reactiveformsmodule,并把它放到ngmodule的imports数组中去。

formcontrol:

当使用响应式表单时,formcontrol 是最基本的构造块。要注册单个的表单控件,请在组件中导入 formcontrol 类,并创建一个 formcontrol 的新实例,把它保存在类的某个属性中。

formgroup

正如 formcontrol 的实例能让你控制单个输入框所对应的控件,formgroup 可以跟踪一组 formcontrol 实例(比如一个表单)的表单状态。当创建 formgroup 时,其中的每个控件都会根据其名字进行跟踪。

formbuilder

当需要与多个表单打交道时,手动创建多个表单控件实例会非常繁琐。formbuilder 服务提供了一些便捷方法来生成表单控件。formbuilder 在幕后也使用同样的方式来创建和返回这些实例,用起来更简单。 ,用 formbuilder 来代替手工创建这些 formcontrol 和 formgroup。

formarray

formarray 是 formgroup 之外的另一个选择,用于管理任意数量的匿名控件。像 formgroup 实例一样,你也可以往 formarray 中动态插入和移除控件,并且 formarray 实例的值和验证状态也是根据它的子控件计算得来的。 不过,你不需要为每个控件定义一个名字作为 key,因此,如果你事先不知道子控件的数量,这就是一个很好的选择。

表单部分模型更新

当修改包含多个控件的 formgroup 的值时,你可能只希望更新模型中的一部分,而不是完全替换掉。

修补(patch)模型值

对单个控件,你会使用 setvalue() 方法来该控件设置新值。但当应用到 formgroup 并打算整体设置该控件的值时,setvalue() 方法会受到这个 formgroup 结构的很多约束。patchvalue() 方法就宽松多了,它只会替换表单模型中修改过的那些属性,因为你只想提供部分修改。setvalue() 中严格的检查可以帮你捕获复杂表单嵌套时可能出现的错误,而 patchvalue() 将会默默地走向失败。

eg:

 this.profileform.patchvalue({
    firstname: 'nancy',
    address: {
      street: '123 drew street'
    }
  });

先举一个不使用formbuilder服务创建控件的方法

import { component, oninit } from '@angular/core';
import { formgroup, formcontrol, formarray } from '@angular/forms';

@component({
  selector: 'app-reactive-form',
  templateurl: './reactive-form.component.html',
  styleurls: ['./reactive-form.component.css']
})
export class reactiveformcomponent implements oninit {
  formmodel: formgroup = new formgroup({
    daterange: new formgroup({
      from: new formcontrol(),
      to: new formcontrol()
    }),
    emails: new formarray([
      new formcontrol('aaa@a.com'),
      new formcontrol('bbb@b.com'),
    ]
  )
  });
  username: formcontrol = new formcontrol('aa');
  constructor() { }

  ngoninit() {
  }
  addemail(): void {
    const emails = this.formmodel.get('emails') as formarray;
    emails.push(new formcontrol());
  }
  onsubmit(): void {
    console.log(this.formmodel);
  }

}

模板

  

起始日期: 截止日期:

再举一个使用formbulider服务创建表单控件的例子,生成一个注册组件

import { component, oninit } from '@angular/core';
import {formgroup, formbuilder, formcontrol, validators } from '@angular/forms';
import { mobilevalidator, equalvalidator } from '../validator/validators';


@component({
  selector: 'app-righster-form',
  templateurl: './righster-form.component.html',
  styleurls: ['./righster-form.component.css']
})
export class righsterformcomponent implements oninit {
  rigisterform: formgroup;
  iscansubmit: boolean;
  constructor(private fb: formbuilder) { }

  ngoninit() {
    this.createform();
  }
  createform() {
    this.rigisterform = this.fb.group({
      username: ['', [validators.required, validators.minlength(6)]],
      mobile: ['', mobilevalidator],
      passwordgroup: this.fb.group({
        password: ['', [validators.minlength(6)]],
        pconfirm: ['']
      }, {validator: equalvalidator})
    });
  }
  // 提交
  onsubmit() {
    const isvalid: boolean = this.rigisterform.get('username').valid;
    // console.log(isvalid);
    // console.log( this.rigisterform.get('username'));
    if (this.rigisterform.valid) {
      console.log(this.rigisterform.value);
    }
  }

}

其中关于验证的可以先忽略;

模板代码:


用户注册

用户名是必填项

用户名最小长度是6

请输入正确的手机号码

密码长度最少6位

两次密码输入不一致

{{ rigisterform.status }}

可以使用rigisterform.get(formcontrolname).value获取每个控件的值,

rigisterform.value可以获取整个表单的数据

rigisterform.status可以获取表单验证是否通过,是表单所有的验证规则。

3.表单验证

3. 1模板驱动验证

为了往模板驱动表单中添加验证机制,你要添加一些验证属性,就像原生的 html 表单验证器。 angular 会用指令来匹配这些具有验证功能的指令。

每当表单控件中的值发生变化时,angular 就会进行验证,并生成一个验证错误的列表(对应着 invalid 状态)或者 null(对应着 valid 状态)。

eg:



name is required.

name must be at least 4 characters long.

name cannot be bob.

3.2响应式表单验证

在响应式表单中,真正的都在组件类中。不应该通过模板上的属性来添加验证器,而应该在组件类中直接把验证器函数添加到表单控件模型上(formcontrol)。然后,一旦控件发生了变化,angular 就会调用这些函数。

验证器函数

有两种验证器函数:同步验证器和异步验证器。

同步验证器函数接受一个控件实例,然后返回一组验证错误或 null。你可以在实例化一个 formcontrol 时把它作为构造函数的第二个参数传进去。 异步验证器函数接受一个控件实例,并返回一个承诺(promise)或可观察对象(observable),它们稍后会发出一组验证错误或者 null。你可以在实例化一个 formcontrol 时把它作为构造函数的第三个参数传进去。

上面2.2中最后一个例子使用的就是响应式表单验证。

自定义验证器,2.2最后一个例子就有两个自定义验证器,mobilevalidator和equalvalidator分别验证手机号和密码,自定义验证器代码如下:

import {formgroup, formcontrol } from '@angular/forms';
export function mobilevalidator(control: formcontrol): any {
    const myreg = /^1[0-9]{10}$/;
    const valid = myreg.test(control.value);
    console.log('mobile的校验值为' + valid);
    return valid  null : { mobile: true };
  }
  export function equalvalidator(group: formgroup): any {
    const pass = group.get('password') as formcontrol;
    const pconfirm = group.get('pconfirm') as formcontrol;
    const valid: boolean = (pass.value === pconfirm.value);
    console.log('密码校验结果' + valid);
    return valid  null : { equal: true };
  }

自定义表单添加到响应式表单中很简单,直接把这个函数放到formcontrol就行了。

添加到模板驱动表单

在模板驱动表单中,你不用直接访问 formcontrol 实例。所以不能像响应式表单中那样把验证器传进去,而应该在模板中添加一个指令。