zoukankan      html  css  js  c++  java
  • ng-book札记——表单

    Angular表单的基本对象为FormControl与FormGroup。

    FormControl

    FormControl代表单个input表单字段(field),即Angular表单的最小单元。
    FormControl封装了表单字段的值与状态(valid, dirty, errors)。

    在TypeScript中创建FormControl:

    // create a new FormControl with the value "Nate"
    let nameControl = new FormControl("Nate");
    
    let name = nameControl.value; // -> Nate
    
    // now we can query this control for certain values:
    nameControl.errors // -> StringMap<string, any> of errors
    nameControl.dirty // -> false
    nameControl.valid // -> true
    

    在DOM中绑定:

    <input type="text" [formControl]="nameControl" />
    

    FormGroup

    FormGroup是FormControl集合的包装器。

    let personInfo = new FormGroup({
      firstName: new FormControl("Nate"),
      lastName: new FormControl("Murray"),
      zip: new FormControl("90210")
    })
    

    由于FormGroup与FormControl继承了相同的基类(AbstractControl),这意味着可以像FormControl一样检查其值与状态。

    personInfo.value; // -> {
    // firstName: "Nate",
    // lastName: "Murray",
    // zip: "90210"
    // }
    
    // now we can query this control group for certain values, which have sensible
    // values depending on the children FormControl's values:
    personInfo.errors // -> StringMap<string, any> of errors
    personInfo.dirty // -> false
    personInfo.valid // -> true
    

    Angular中使用表单有FormsModule与ReactiveFormsModule两种方式。

    FormsModule

    导入FormsModule后, 将自动对相关视图中的任意<form>标签附加NgForm。
    NgForm提供两样功能:

    1. 名为ngForm的FormGroup
    2. (ngSubmit)
    import {
      FormsModule
    } from '@angular/forms';
    
    // farther down...
    
    @NgModule({
      declarations: [
        FormsDemoApp,
        DemoFormSkuComponent,
        // ... our declarations here
      ],
      imports: [
        BrowserModule,
        FormsModule, // <-- add this
      ],
      bootstrap: [ FormsDemoApp ]
    })
    class FormsDemoAppModule {}
    
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-demo-form-sku',
      templateUrl: './demo-form-sku.component.html',
      styles: []
    })
    export class DemoFormSkuComponent implements OnInit {
    
      constructor() { }
    
      ngOnInit() {
      }
    
      onSubmit(form: any): void {
        console.log('you submitted value:', form);
      }
    }
    
    <div class="ui raised segment">
      <h2 class="ui header">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"
          id="skuInput"
          placeholder="SKU"
          name="sku" ngModel>
      </div>
    
      <button type="submit" class="ui button">Submit</button>
      </form>
    </div>
    

    #f="ngForm"为视图创建一个本地变量f,并绑定了ngForm。这样在视图的其它地方就可以灵活使用,比如在(ngSubmit)="onSubmit(f.value)中。

    在input元素里,单独的ngModel特性表示一个单向绑定,以及在表单中创建一个名为sku的FormControl,并且自动添加至父级的FormGroup(这里是form)。

    ReactiveFormsModule

    这种方式下可以通过FormBuilder帮助创建FormGroup与FormControl。

    import {
      ReactiveFormsModule
    } from '@angular/forms';
    
    // farther down...
    
    @NgModule({
      declarations: [
        FormsDemoApp,
        DemoFormSkuComponent,
        // ... our declarations here
      ],
      imports: [
        BrowserModule,
        ReactiveFormsModule // <-- and this
      ],
      bootstrap: [ FormsDemoApp ]
    })
    class FormsDemoAppModule {}
    
    import { Component, OnInit } from '@angular/core';
    import {
      FormBuilder,
      FormGroup
    } from '@angular/forms';
    
    @Component({
      selector: 'app-demo-form-sku-with-builder',
      templateUrl: './demo-form-sku-with-builder.component.html',
      styles: []
    })
    export class DemoFormSkuWithBuilderComponent implements OnInit {
      myForm: FormGroup;
    
      constructor(fb: FormBuilder) {
        this.myForm = fb.group({
        'sku': ['ABC123']
        });
      }
    
      ngOnInit() {
      }
    
      onSubmit(value: string): void {
        console.log('you submitted value: ', value);
      }
    }
    
    <div class="ui raised segment">
      <h2 class="ui header">Demo Form: Sku with Builder</h2>
      <form [formGroup]="myForm"
        (ngSubmit)="onSubmit(myForm.value)"
        class="ui form">
    
      <div class="field">
        <label for="skuInput">SKU</label>
        <input type="text"
          id="skuInput"
          placeholder="SKU"
          [formControl]="myForm.controls['sku']">
      </div>
    
      <button type="submit" class="ui button">Submit</button>
      </form>
    </div>
    

    视图中通过[formGroup]="myForm"绑定已创建的FormGroup,同时onSubmit也改为myForm.value。
    而对于input元素,现在借由[formControl]="myForm.controls['sku']"方式绑定已创建的FormControl。

    验证

    向一个FormControl添加验证器很简单,只需要将其传入第二个参数。

    let control = new FormControl('sku', Validators.required);
    

    如果是FormBuilder的话,可以使用以下语法:

    import { Component } from '@angular/core';
    import {
      FormBuilder,
      FormGroup,
      Validators,
      AbstractControl
    } from '@angular/forms';
    
    @Component({
      selector: 'app-demo-form-with-validations-explicit',
      templateUrl: './demo-form-with-validations-explicit.component.html',
      styles: []
    })
    export class DemoFormWithValidationsExplicitComponent {
      myForm: FormGroup;
      sku: AbstractControl;
    
      constructor(fb: FormBuilder) {
        this.myForm = fb.group({
        'sku': ['', Validators.required]
      });
    
        this.sku = this.myForm.controls['sku'];
      }
    
      onSubmit(value: string): void {
        console.log('you submitted value: ', value);
      }
    }
    
    <div class="ui raised segment">
    <h2 class="ui header">Demo Form: with validations (explicit)</h2>
    <form [formGroup]="myForm"
      (ngSubmit)="onSubmit(myForm.value)"
      class="ui form"
      [class.error]="!myForm.valid && myForm.touched">
    
        <div class="field"
          [class.error]="!sku.valid && sku.touched">
          <label for="skuInput">SKU</label>
          <input type="text"
            id="skuInput"
            placeholder="SKU"
            [formControl]="sku">
          <div *ngIf="!sku.valid"
            class="ui error message">SKU is invalid</div>
          <div *ngIf="sku.hasError('required')"
            class="ui error message">SKU is required</div>
        </div>
    
        <div *ngIf="!myForm.valid"
          class="ui error message">Form is invalid</div>
    
        <button type="submit" class="ui button">Submit</button>
      </form>
    </div>
    

    * 通过myForm的valid属性值可以判断所有FormControl是否皆有效。
    * [class.error]可以根据FormControl有效与否变更样式。
    * sku.hasError('required'),可以指定特定的验证要求。

    验证器还能够按照需求定制:

    function skuValidator(control: FormControl): { [s: string]: boolean } {
      if (!control.value.match(/^123/)) {
        return {invalidSku: true};
      }
    }
    
    constructor(fb: FormBuilder) {
      this.myForm = fb.group({
        'sku': ['', Validators.compose([
        Validators.required, skuValidator])]
      });
    
    <div *ngIf="sku.hasError('invalidSku')"
      class="ui error message">SKU must begin with <span>123</span></div>
    

    监察

    FormGroup与FormControl都有自己的EventEmitter,可以用于观察变化。
    方式很简单,使用其valueChanges的subscribe方法进行订阅。

    constructor(fb: FormBuilder) {
      this.myForm = fb.group({
        'sku': ['', Validators.required]
      });
    
      this.sku = this.myForm.controls['sku'];
    
      this.sku.valueChanges.subscribe(
        (value: string) => {
          console.log('sku changed to:', value);
        }
      );
    
      this.myForm.valueChanges.subscribe(
        (form: any) => {
          console.log('form changed to:', form);
        }
      );
    }
    
  • 相关阅读:
    修改 Mac 默认 PHP 运行环境,给 MAMP 配置全局 Composer
    修改 Mac 默认 PHP 运行环境,给 MAMP 配置全局 Composer
    Intellij Idea/Webstorm/Phpstorm 的高效快捷键
    Intellij Idea/Webstorm/Phpstorm 的高效快捷键
    管理工具推荐
    mongo find
    redis 工具
    Redis Quick Start [熟练版]
    Redis cluster
    redis cluster 使用中出现的问题
  • 原文地址:https://www.cnblogs.com/kenwoo/p/8878151.html
Copyright © 2011-2022 走看看