直接獻(xiàn)上代碼
父組件
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">關(guān)</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);
}
}
簡(jiǎn)單說(shuō)明:
NG_VALUE_ACCESSOR
原文說(shuō)明:
Used to provide a ControlValueAccessor for form controls.
為ControlValueAccessor提供注入
ControlValueAccessor:
這是實(shí)現(xiàn)雙向綁定的核心
原文說(shuō)明:
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.
大意是讓一個(gè)DOM元素像input空間一樣去展示數(shù)據(jù)
其中registerOnChange和registerOnTouched是必須實(shí)現(xiàn)的方法蛙粘。
useExisting: forwardRef(() => TwoWayComponent),
如果少了這一段,會(huì)報(bào)錯(cuò)
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的)必須被指派一個(gè)component
InjectionToke
原文說(shuō)明:
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.
大意是讓你在接口溉知、類在還沒實(shí)例化之前調(diào)用
forwardRef
原文說(shuō)明:
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服務(wù)的,讓有DI未定義的token能夠使用
multi: true
少了會(huì)報(bào)錯(cuò)
應(yīng)該是為NG_VALUE_ACCESSOR能讓forEach而服務(wù)的