1. 程式人生 > >簡單實現angular2組件雙向綁定(轉)

簡單實現angular2組件雙向綁定(轉)

exp mpat comment 空間 pri orm ima 調用 NPU

直接獻上代碼
父組件

import { Component, OnInit } from ‘@angular/core‘;

@Component({
  selector: ‘ngx-input‘,
  templateUrl: `
    <p>雙向綁定</p>
    {{pvalue}} <input type="radio" [attr.value]="pvalue" [checked]="pvalue" (change)="pvalue=!pvalue">
    <br>
    <p>雙向子組件</p>
    <ngx-two-way [(ngModel)]="pvalue"></ngx-two-way>
`
})
export class InputComponent {

  pvalue = false;

  constructor() { }
}

子組件

import {Component, forwardRef} from ‘@angular/core‘;
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from ‘@angular/forms‘

@Component({
  selector: ‘ngx-two-way‘,
  templateUrl:`
    <div class="toggle-button-container">
      <a href="javascript:;"  (click)="toggle()" class="text-close" *ngIf="!model">關</a>
      <a href="javascript:;"  (click)="toggle()" class="text-open" *ngIf="model">開</a>
  </div>
  `,
  providers: [{
        provide: NG_VALUE_ACCESSOR,
        useExisting: forwardRef(() => TwoWayComponent),
        multi: true
    }]
})
export class TwoWayComponent implements ControlValueAccessor {

  constructor() { }

  private model: any;

  public onModelChange: Function = () => {};
  public onModelTouched: Function = () => {};
  writeValue(value: any) {
      this.model = value;
  }
  registerOnChange(fn: Function): void {
      this.onModelChange = fn;
  }
  registerOnTouched(fn: Function): void {
      this.onModelTouched = fn;
  }

  // setDisabledState(val: boolean): void {}

  toggle(event) {
    this.model = !this.model;
    this.onModelChange(this.model);
  }
}

簡單說明:

NG_VALUE_ACCESSOR

原文說明:
Used to provide a ControlValueAccessor for form controls.
為ControlValueAccessor提供註入

ControlValueAccessor:

這是實現雙向綁定的核心
原文說明:
A bridge between a control and a native element.
A ControlValueAccessor abstracts the operations of writing a new value to a DOM element representing an input control.
大意是讓一個DOM元素像input空間一樣去展示數據
其中registerOnChange和registerOnTouched是必須實現的方法。

useExisting: forwardRef(() => TwoWayComponent),

如果少了這一段,會報錯

技術分享圖片 image.png
 Argument of type ‘{ selector: string; templateUrl: string; styleUrls: string[]; providers: { provide: InjectionToke...‘ is not assignable to parameter of type ‘Component‘.
  Types of property ‘providers‘ are incompatible.
    Type ‘{ provide: InjectionToken<ControlValueAccessor>; }[]‘ is not assignable to type ‘Provider[]‘.
      Type ‘{ provide: InjectionToken<ControlValueAccessor>; }‘ is not assignable to type ‘Provider‘.
        Type ‘{ provide: InjectionToken<ControlValueAccessor>; }‘ is not assignable to type ‘FactoryProvider‘.
          Property ‘useFactory‘ is missing in type ‘{ provide: InjectionToken<ControlValueAccessor>; }‘.

大意是InjectionToke(在NG_VALUE_ACCESSOR中import的)必須被指派一個component

InjectionToke

原文說明:
Creates a token that can be used in a DI Provider.
Use an InjectionToken whenever the type you are injecting is not reified (does not have a runtime representation) such as when injecting an interface, callable type, array or parametrized type.

InjectionToken is parametrize on T which is the type of object which will be returned by the Injector. This provides additional level of type safety.
大意是讓你在接口、類在還沒實例化之前調用

forwardRef

原文說明:
Allows to refer to references which are not yet defined.

For instance, forwardRef is used when the token which we need to refer to for the purposes of DI is declared, but not yet defined. It is also used when the token which we use when creating a query is not yet defined.
為InjectionToke服務的,讓有DI未定義的token能夠使用

multi: true

少了會報錯

技術分享圖片 image.png

應該是為NG_VALUE_ACCESSOR能讓forEach而服務的



作者:琢磨先生lf
鏈接:https://www.jianshu.com/p/75b59181a5d9
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並註明出處。

簡單實現angular2組件雙向綁定(轉)