zoukankan      html  css  js  c++  java
  • ng2 学习笔记(二)表单及表单验证

    在上一篇文章中提到了表单,只说了表单的数据绑定,这一篇文章主要讲一下表单验证,为什么把表单单独拿出来学习,主要是因为,表单是商业应用的支柱,我们用它来执行登录、求助、下单、预订机票、安排会议,以及不计其数的其它数据录入任务,使用频率非常高。所以这块的重要性就显而易见了。

    正文开始,这篇文章还是适合初学者,如果是大神,请指正不足:

    先来看一下最终的样子:

    表单很简单,模拟新增客户,用到表单的不少控件,

    首先,要使用angular 的表单的一些控件,在使用ngModel做双向数据绑定之前,得先导入FormsModule, 把它加入 Angular 模块的imports列表。

    在加载之前写组件。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 { UserForm } from './form.component'; // 引入自定义的组件
    
    @NgModule({
      imports:      [ BrowserModule ,FormsModule],
      declarations: [ AppComponent,UserForm],
      bootstrap:    [ AppComponent ]
    })
    
    export class AppModule { }

    下面我们主要看一下表单这个组件内部的一些细节:

     1 import { Component } from '@angular/core';
     2 
     3 @Component({
     4     selector:'hero-form',
     5     template:`
     6         <h2>FORM 表单</h2>
     7         <hr />
     8         <div class="container">
     9             <div class="row">
    10                 <div class="col-sm-6 col-sm-offset-3">
    11                     <h4>客户管理</h4>
    12                     <form #forms="ngForm">
    13                         <div class="alert alert-danger" [hidden]="forms.form.valid">表单填写不合法</div>
    14                         <div class="form-group">
    15                             <label [class.text-danger]="!name.valid && forms.form.controls.name.touched">姓名</label>
    16                             <input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required>
    17                         </div>
    18                         <div class="form-group">
    19                             <label [class.text-danger]="!sex.valid && forms.form.controls.sex.touched">性别</label>
    20                             <select class="form-control" [(ngModel)]="model.sex" required name="sex" #sex="ngModel">
    21                                 <option *ngFor="let s of sexs" [ngValue]="s">{{s}}</option>
    22                             </select>
    23                         </div>
    24                         <div class="form-group">
    25                             <label>来源</label>
    26                             <div>
    27                                 <label class="checkbox-inline" *ngFor="let f of froms">
    28                                       <input type="radio" [value]="f" name="from" [(ngModel)]="model.from" #from="ngModel" required> {{f}}
    29                                 </label>
    30                             </div>
    31                         </div>
    32                         <div class="form-group">
    33                             <label>意向产品</label>
    34                             <div>
    35                                 <label class="checkbox-inline" *ngFor="let p of model.mayBuy">
    36                                       <input type="checkbox" [(ngModel)]="p.chose" [value]="p.pid" name="mayBuy" required> {{p.pname}}
    37                                 </label>
    38                             </div>
    39                         </div>
    40                         <button type="button" (click)="submit(forms.form)" [class.btn-danger]="!forms.form.valid" [disabled]="!forms.form.valid" class="btn btn-primary">提交</button>
    41                     </form>
    42                 </div>
    43             </div>
    44         </div>
    45     `
    46 }) //这里有个小坑,如果这里按习惯加一个分号“;”,那就挂了,不能编译
    47 
    48 export class UserForm {
    49     sexs = ['男', '女','保密'];
    50     products = [
    51         {
    52             pid:'p_001',
    53             pname:'产品A',
    54             chose:false
    55         }, 
    56         {
    57             pid:'p_001',
    58             pname:'产品B',
    59             chose:false
    60         },
    61         {
    62             pid:'p_001',
    63             pname:'产品C',
    64             chose:false
    65         },
    66         {
    67             pid:'p_001',
    68             pname:'产品D',
    69             chose:false
    70         }
    71     ];
    72     froms = ['新增客户','老客户介绍'];
    73       model = {
    74           name:'',
    75           sex:'',
    76           from:'',
    77           mayBuy:this.products
    78       };
    79       submitted = false;
    80 
    81       submit(a:any){
    82           console.log(this.model,a)
    83       }
    84 }

    普通表单结构以及数据的双向绑定,就不多说了,主要说一下表单验证这块,即红色代码的地方。

    交代一下基础概念,在ng 的表单模块中,单个控件(如:input)都会被跟踪状态,并且会在该控件上增加相应的class:

      1)、控件是否已经被访问过:

          是:touched;class:ng-touched

          否:untouched; class:ng-untouched

      2)、控件的值是否被修改过:

          是:dirty;class:ng-dirty

          否:pristine;class:ng-pristine

      3)、控件的值是否合法:

          是:valid;class:ng-valid

          否:invalid;class:ng-invalid

    整体表单也存在以上的3中状态,表单的验证证是通过这些跟踪的不同状态完成的。那么怎么访问到这些状态呢?

    你可能已经注意到在form标签上有这样一段代码:

    <form #forms="ngForm">

    是的,#forms这个就是模版引用变量,上一篇文章提到过,这里只是把#forms初始化为 "ngForm";
    现在我们就可以通过forms这个对象访问到我们需要的状态了,如果你不知道forms里都有啥,怎么用,那你就写个方法,把它打印出来,(click)="submit(forms)" 就可以了。
    还有一个要注意的点,就是针对类似
    <input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required>
    这样的,name属性是必须要添加的,如果要对单个控件进行验证,我们可以加上模版引用变量#name="ngModel"快速访问到这个控件。
    如果你需要正则表达式验证,只需加入pattern属性即可;
    <input type="text" class="form-control" pattern="[a-zA-Z ]*" [(ngModel)]="model.name" name="name" />

    以上述代码为例主要有以下几个点:

    1、整体表单的合法性验证:

      代码:forms.form.STATE,例如:forms.form.valid;forms.form.invalid

    2、单个表单控件验证:

      以这段代码为例:  

    1 <div class="form-group">
    2   <label [class.text-danger]="!name.valid && forms.form.controls.name.touched">姓名</label>
    3   <input type="text" class="form-control" name="name" [(ngModel)]="model.name" #name="ngModel" required>
    4 </div>

    这里的label的显示样式的判断条件其实是两种判断方法,

      1)、!name.valid这个是使用模板引用变量来判断的;

      2)、forms.form.controls.name.touched是使用forms.form这个对象判断的。

    注意:forms.form这个对象里有很多子对象,这里使用的是form下controls这个对象查找到name判断的,至于是否应该controls这个子对象,有待研究。

    本文到此结束,只是表单的一些初级应用,如果想了解更多,请点击这里查看API文档。

    欢迎大家对本文所涉及的内容进行探讨,对有误的地方进行指正。

    感谢阅读。

  • 相关阅读:
    Java NIO使用及原理分析(二)(转)
    Java NIO使用及原理分析 (一)(转)
    虚拟机字节码执行引擎
    虚拟机类加载机制
    浅析Java中的final关键字
    java内存模型7-处理器内存模型
    java内存模型6-final
    最小生成树
    有向图的基本算法
    并查集(Union-Find)算法介绍
  • 原文地址:https://www.cnblogs.com/wwlhome/p/6430166.html
Copyright © 2011-2022 走看看