angular5 Reactive Form動態表單

Angular5 Reactive Form

根據最近的使用, 總結一下在ngx中使用reactive formcss

1. 建立表單

需求: 建立一個帶驗證的表單, 若是表單驗證不經過則提交按鈕disabled=truehtml

<!-- app.component.html -->

<form [formGroup]="form">

  <div class="form-group">
    <label for="">name: </label>
    <input type="text" formControlName="name">
  </div>
  <div class="form-group">
    <label for="">password: </label>
    <input type="password" formControlName="password">
  </div>

  <div class="form-group">
    <button type="submit" (click)="submit()" [disabled]="form.invalid">submit</button>
    <button type="button" (click)="reset()">reset</button>
  </div>
    
</form>
// app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  name = 'app';

  form: FormGroup;

  constructor(
    private fb: FormBuilder
  ){}

  ngOnInit(){
    this.form = this.fb.group({
      name: ['', Validators.required],
      password: ['', [Validators.required, Validators.minLength(6)]]
    });
  }

  submit(){
    if(this.form.valid){
      console.log('submiting...')
    }else{
      console.log('form is not valid')
    }
  }

  reset(){
    this.form.reset();
  }
}

2. 自定義驗證器

需求: 密碼須要格式爲數字字母下劃線6-12位react

參考: Custom validatorstypescript

// app.component.ts

...

// 自定義密碼驗證
function ValidPwd(control: AbstractControl):any {
  const reg = /^\w{6,12}$/;
  if(reg.test(control.value)){
    // 經過驗證時須要返回 null
    return null;
  }
  return {status: 'error', message: '密碼格式爲數字字母下劃線6-12位'}
}

...
export class AppComponent implements OnInit {
...
  ngOnInit(){
    this.form = this.fb.group({
      name: ['', Validators.required],
      password: ['', [Validators.required, ValidPwd]]
    });
  }
...
}

3. 動態建立表單

需求: 表單增長朋友選項, 默認顯示一個, 能夠增長/刪除api

<!-- app.component.html -->

<form [formGroup]="form">

  <div class="form-group">
    <label for="">name: </label>
    <input type="text" formControlName="name">
  </div>
    
  <div class="form-group">
    <label for="">password: </label>
    <input type="password" formControlName="password">
  </div>

  <ng-container *ngFor="let friend of friends.controls; let i=index">
    <div class="form-group">
      <label for="">friend(s): </label>
      <input type="text" [formControl]="friend">
      <span class="cursor-pointer hover-red" (click)="addFriend()" *ngIf="i===0">+</span>
      <span class="cursor-pointer hover-red" *ngIf="i!==0" (click)="removeFriend(i)">-</span>
    </div>
  </ng-container>

  <div class="form-group">
    <button type="submit" (click)="submit()" [disabled]="form.invalid">submit</button>
    <button type="button" (click)="reset()">reset</button>
  </div>

</form>
// app.component.ts

...

export class AppComponent implements OnInit {
  name = 'app';

  form: FormGroup;
  friends;

  constructor(
    private fb: FormBuilder
  ) {}

  ngOnInit() {
    this.form = this.fb.group({
      name: ['', Validators.required],
      password: ['', [Validators.required, ValidPwd]],
      friends: this.fb.array([this.createFriend()])
    });

    this.friends = this.form.get('friends') as FormArray;
  }

  /**
   * 動態建立表單
   * @returns {FormControl}
   */
  createFriend() {
    return this.fb.control('', Validators.required);
  }

  /**
   * 增長輸入框
   */
  addFriend(): void {
    this.friends.push(this.createFriend());

  }

  /**
   * 移除輸入框
   * @param {number} i
   */
  removeFriend(i: number): void {
    this.friends.removeAt(i);
  }

...

}

圖片描述

4. standalone

需求: 增長單選框控制表單app

在Reactive表單中, 使用ngModel時, 會出現報錯ide

Error: 
      ngModel cannot be used to register form controls with a parent formGroup directive.

報錯中也提示了, 應該在input中增長[ngModelOptions]="{standalone: true}"ui

文檔中是這麼介紹的:this

standalone: Defaults to false. If this is set to true, the ngModel will not register itself with its parent form, and will act as if it's not in the form. This can be handy if you have form meta-controls, a.k.a. form elements nested in the <form> tag that control the display of the form, but don't contain form data.

如今表單變成這樣:spa

<!-- app.component.html -->

<form [formGroup]="form">

  <div class="form-group">
    <label for="">name: </label>
    <input type="text" formControlName="name">
  </div>
  <div class="form-group">
    <label for="">password: </label>
    <input type="password" formControlName="password">
  </div>

  <ng-container
    *ngFor="let friend of friends.controls; let i=index">
    <div class="form-group">
      <label for="">friend(s): </label>
      <input type="text" [formControl]="friend">
      <span class="cursor-pointer hover-red" (click)="addFriend()" *ngIf="i===0">+</span>
      <span class="cursor-pointer hover-red" *ngIf="i!==0" (click)="removeFriend(i)">-</span>
    </div>
  </ng-container>

  <div class="form-group">
    <label for="">contactType: </label>
    mobile<input type="radio" value="0" [(ngModel)]="contactType" [ngModelOptions]="{standalone:true}">&emsp;
    landLine<input type="radio" value="1" [(ngModel)]="contactType" [ngModelOptions]="{standalone:true}">
  </div>

  <div class="form-group">
    <label for="">{{+contactType === 1?"landLine":"mobile"}}: </label>
    <input type="text" formControlName="contact">
  </div>

  <div class="form-group">
    <button type="submit" (click)="submit()" [disabled]="form.invalid">submit</button>
    <button type="button" (click)="reset()">reset</button>
  </div>

</form>

app.componen.ts中增長contactType變量, 表單實例中增長contact:

// app.component.ts

...

export class AppComponent implements OnInit {
  name = 'app';

  form: FormGroup;
  friends;
  contactType:number = 0;

  constructor(
    private fb: FormBuilder
  ) {}

  ngOnInit() {
    this.form = this.fb.group({
      name: ['', Validators.required],
      password: ['', [Validators.required, ValidPwd]],
      friends: this.fb.array([this.createFriend()]),
      contact: ['', Validators.required]
    });

    this.friends = this.form.get('friends') as FormArray;
  }

  /**
   * 動態建立表單
   * @returns {FormControl}
   */
  createFriend() {
    return this.fb.control('', Validators.required);
  }

  /**
   * 增長輸入框
   */
  addFriend(): void {
    this.friends.push(this.createFriend());

  }

  /**
   * 移除輸入框
   * @param {number} i
   */
  removeFriend(i: number): void {
    this.friends.removeAt(i);
  }

  submit() {
    if (this.form.valid) {
      console.log('submitting...');
    } else {
      console.log('form is not valid');
    }
  }

  reset() {
    this.form.reset();
  }
}
相關文章
相關標籤/搜索