模板式表单校验和 表单处理实战

模板式表单校验

  1. 在模板式表单中后台没有像响应式的数据模型,指令是唯一能使用的东西,需要将校验器方法包装成指令,然后在模板中使用
  2. 在模板式表单中还可以使用angular默认已经定义的校验器required和minlength等,但是为了避免和HTML中的属性发生冲突可以使用novalidate来关闭浏览器默认的表单校验
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)" novalidate>

  <div>手机号:<input ngModel required name="mobile" type="number"></div>

  <button type="submit">注册</button>
</form>
  1. 使用ng命令生成一个指令

ng g directive directives/mobileValidator

  1. 指令 就是一个没有模板的组件,组件作为标签来使用,指令可以作为HTML的属性来使用
  2. 将之前写的校验方法包装到指令中去,在装饰器中写一个providers提供器,校验器的包装指令的token是固定的NG_VALIDATORS
  3. 将校验手机号的方法包装成指令
import { Directive } from '@angular/core';
import {NG_VALIDATORS} from '@angular/forms';
import {mobileValidator} from '../validator/validators';

@Directive({
  selector: '[mobile]',
  providers:[{provide:NG_VALIDATORS, useValue:mobileValidator ,multi:true}]
})
export class MobileValidatorDirective {

  constructor() { }

}
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)" novalidate>
  <div>用户名:<input ngModel required minlength="6" name="username" type="text"></div>
  <div>手机号:<input ngModel  mobile name="mobile" type="number"></div>
<div ngModelGroup="passwordsGroup" equal>
  <div>密码:<input ngModel minlength="6" name="password" type="password"></div>
  <div>确认密码:<input ngModel name="pconfirm" type="password"></div>
</div>
  <button type="submit">注册</button>
</form>
  1. 模板式表单中由于组件里没有可以编程控制的数据模型,所以如果想要在了解表单中的任何信息,都要从模板式将信息传给组件控制器,在提交表单时,为了得知表单是否有效只能在onSubmit方法中传入
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value,myForm.valid)" novalidate>
   <button type="submit">注册</button>
</form>
onSubmit(value:any,valid:boolean){
  console.log(valid);
  console.log(value);
}
  1. 与响应式表单相同使用hasError方法显示错误信息,但是由于模板式表单并没有formModel属性,所以使用myForm.form来调用hasError方法,
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value,myForm.valid)" novalidate>
  <div>用户名:<input ngModel required minlength="6" name="username" type="text"></div>
  <div [hidden]="myForm.form.get('username').valid || formModel.get('username').untouched">
    <div [hidden]="!myForm.form.hasError('required','username')">
      用户名是必填项
    </div>
    <div [hidden]="!myForm.form.hasError('minlength','username')">
      用户最小长度为6
    </div>
  </div>
  <div>手机号:<input ngModel  mobile name="mobile" type="number"></div>
  <div [hidden]="!myForm.form.hasError('mobile','mobile')||formModel.get('mobile').untouched">
    请输入正确的mobile
  </div>
<div ngModelGroup="passwordsGroup" equal>
  <div>密码:<input ngModel minlength="6" name="password" type="password"></div>
  <div [hidden]="!myForm.form.hasError('minlength',['passwordsGroup','password'])">
    密码最小长度为6
  </div>
  <div>确认密码:<input ngModel name="pconfirm" type="password"></div>
</div>
  <div [hidden]="!myForm.form.hasError('equal','passwordsGroup')">
    {{myForm.form.getError('equal','passwordsGroup')?.descxx}}
  </div>
  <button type="submit">注册</button>
</form>
  1. 通过状态属性来决定是否显示,但是不能这样myForm.form.get('username').valid||formModel.get('username').untouched直接获取状态属性值
  2. 模板式表单和响应式表单不同,它的模型的值和状态的变更是异步的,而且很难控制,如果使用同步的方式去访问这些属性就会报错,如果在模板式表单中访问这些属性,使用input属性绑定
<form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value,myForm.valid)" novalidate>
  <div>用户名:<input ngModel required minlength="6" name="username" (input)="onMobileInput(myForm)" type="text"></div>
  <div [hidden]="mobileValid||mobileUntouched">
    <div [hidden]="!myForm.form.hasError('required','username')">
      用户名是必填项
    </div>
    <div [hidden]="!myForm.form.hasError('minlength','username')">
      用户最小长度为6
    </div>
  </div>
  </div>
  <button type="submit">注册</button>
</form>

mobileValid:boolean=true;
mobileUntouched=true;

onMobileInput(form: NgForm) {
  if(form){
    this.mobileValid=form.form.get("mobile").valid;
    this.mobileUntouched=form.form.get("mobile").untouched;
  }
}

表单处理实战

  1. 需要实现的功能
    处理商品搜索表单
    在商品名称中输入时,提示最少输入三个字
    在商品价格中输入负数时,提示商品价格不能为负数
    商品类别中展示所以的商品类别
    点击搜索时,如果表单中有字段不合法时,控制中不打印任何数据
  2. 往productService添加一个新的方法来获取所有可用商品类别
getAllCategories():string[]{
  return ["电子产品","硬件设备","图书"];
}
  1. 使用响应式表单完成效果
export class SearchComponent implements OnInit {


  formModel: FormGroup;

  categories: string[];

  constructor(private productService:ProductService) {
    let fb=new FormBuilder();
    this.formModel=fb.group({
      title:['',Validators.minLength(3)],
      price:[null,this.positiveNumberValidator],
      category:['-1']
    })

  }

  ngOnInit() {
    this.categories=this.productService.getAllCategories();
  }

  positiveNumberValidator(control: FormControl): any {
    let value = control.value;
    if (!value) {
      return null;
    }
    let price = parseInt(value);

    if (price > 0) {
      return null;
    } else {
      return { positiveNumber: true }
    }
  }

  onSubmit(): void {
    if (this.formModel.valid) {
      console.log(this.formModel.value)
    }
  }

}
 }
  1. 建立一个表单的数据模型,将数据模型和模板HTML元素连接起来
<form [formGroup]="formModel" (ngSubmit) = "onSubmit()" novalidate>
  <div class="form-group" [class.has-error]="formModel.hasError('minlength','title')">
    <label for="productTitle">商品名称:</label>
    <input type="text" formControlName="title" id="productTitle"  class="form-control" placeholder="商品名称">
    <span class="help-block" [class.hidden]="!formModel.hasError('minlength','title')">请至少输入三个字符</span>
  </div>
  <div class="form-group" [class.has-error]="formModel.hasError('positiveNumber','price')">
    <label for="productPrice">商品价格:</label>
    <input type="text" formControlName="price" id="productPrice" name="productPrice" class="form-control" placeholder="商品价格">
    <span class="help-block" [class.hidden]="!formModel.hasError('positiveNumber','price')">请输入正数</span>
  </div>
  <div class="form-group">
    <label for="productCategory">商品类别:</label>
    <select formControlName="category" class="form-control" id="productCategory">
      <option value="-1">--全部分类--</option>
      <option  *ngFor="let category of categories" [value]="category">{{category}}</option>
    </select>
  </div>
  <div class="form-group">
    <button type="submit" class="btn btn-primary btn-block">
      搜索
    </button>
  </div>
</form>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • 表单处理 一般情况表单需要具有几个功能: 每一个输入字段都需要有独立的校验规则 如果用户输入不符合校验规则,就会在...
    2764906e4d3d阅读 2,418评论 0 2
  • angular提供了模板驱动和模型驱动两种方式来构建表单。模板驱动模式使用模板表单内置指令、内置校验的方式来构建表...
    oWSQo阅读 812评论 0 0
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,618评论 4 59
  • 版本:Angular 5.0.0-alpha 表单是商业应用的支柱,我们用它来执行登录、求助、下单、预订机票、安排...
    soojade阅读 1,237评论 0 1
  • 表单的设计 表单可用性测试获取信息:错误或问题的数量和位置 错误或问题的严重程度 完成率 完成整个表单或部分...
    重木啊阅读 3,194评论 0 2