[angular2]對自訂的component實做NgModel和驗證

此篇文章紀錄一下在自訂的component實做NgModel來Two Way Binding還有Template Driven的驗證做法

前言

雖然組件間的溝通,新的框架都不太支援元件間Two Way Binding的做法,但有時候如果只是一個父子組件,沒有很複雜的tree結構的話,Two Way Binding還是很方便的,那這篇就來把自己研究的成果紀綠下來囉。

實做一個簡單的父子元件

我的目標是想在父元件直接用ngModel來做two way binding加上驗證,所以先加上一個子元件就叫child.component,接著看一下child的部份吧

import { NG_VALUE_ACCESSOR, ControlValueAccessor } from "@angular/forms";
import { Component, OnInit, forwardRef } from '@angular/core';

export const CHILD_ACCESSER: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => ChildComponent), //ChildComponent是此component的類別
  multi: true
};


@Component({
  selector: 'app-child',
  template: `
<p>
  <input type="text" [(ngModel)]="message">
</p>
`,
  providers: [CHILD_ACCESSER]
})

export class ChildComponent implements ControlValueAccessor {
  value: string;

  get message() { //取得NgModel的值
    return this.value;
  }

  set message(value) { //寫進NgModel的值
    this.value = value;
    this.notifyValueChange(); //通知父層值已修改
  }


  notifyValueChange() {
    if (this.onChange) {
      this.onChange(this.message);
    }
  }

  onChange: (value) => {};
  onTouched: () => {};

  writeValue(obj: any): void {
    this.message = obj;
    if (!this.message) {
      this.message = null;
    }
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }


  constructor() { }
}

接著再看一下父元件就很簡單了,注意一下name和required是要寫在父元件這層,而不是寫在child這個子元件的input裡面

import { INCREASE_COUNT, REDUCE_COUNT } from './store/action-type';
import { RootState } from './store/root-reducer';
import { Store } from '@ngrx/store';
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { NgForm } from "@angular/forms/src/directives";


@Component({
  selector: 'app-root',
  template:`
<form #myForm="ngForm" novalidate>
  <button (click)="submit(myForm)">submit</button>
  <app-child name="message" [(ngModel)]="message" required></app-child>
  {{message}}
</form>
  `
})
export class AppComponent {
  message = "123";

  constructor() {
  }

  submit(myForm:NgForm){
    console.log(myForm.value,`isValid:${myForm.valid}`);
  }
}

 

結論

這篇很簡單,主要是紀錄給自己以後備查,也希望對需要的人有點幫助。