组件传值双向绑定
output绑定事件,由组件绑定事件EventEmitter向父组件传输信息,属性名+属性后缀Change 是约定的固定写法;
// child.component.html
<h1>status in child: {{childStatus}}</h1>
<button (click)="toggle()">Toggle childStatus</button>
// child.component.ts
import {Component,OnInit,Input,Output,EventEmitter} from '@angular/core';
@Component({
selector: 'test-binding',
templateUrl: './child.component.html'
})
export class ChildComponent implements OnInit{
@Input() childStatus;
@Output() childStatusChange = new EventEmitter();
ngOnInit(){}
toggle(){
this.childStatus = !this.childStatus;
this.childStatusChange.emit(this.childStatus);
}
}
// app.component.html
<test-binding [(childStatus)]="parentStatus"></test-binding>
<h1>status in parent: {{parentStatus}}</h1>
<button (click)="toggle()">Toggle parentStatus</button>
// app.component.ts
import { Component,OnInit } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
parentStatus: boolean = true;
ngOnInit(){
}
toggle(){
this.parentStatus = !this.parentStatus;
}
}
https://stackblitz.com/edit/angular-uagcji
监听数据变化 旧值和新值
通过 ngModelChange 和 BehaviorSubject
<hello name="{{ name }}"></hello>
<p>
Start editing to see some magic happen :)
</p>
<input ngModel (ngModelChange)="value$.next($event)">
<p>Previous value: {{ previousValue }}</p>
<p>Current value: {{ currentValue }}</p>
import { Component, OnInit } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
name = 'Angular 5';
value$ = new BehaviorSubject(null);
previousValue = null;
currentValue = null;
ngOnInit() {
const pairwise$ = this.value$.debounceTime(200).pairwise();
pairwise$.subscribe(([prevous, current]) => {
this.previousValue = prevous;
this.currentValue = current;
});
}
}
https://stackblitz.com/edit/angular-ogetgv?file=index.html
自定义组件使用ngModel
ControlValueAccessor 实现model->view view->model,从而实现的双向绑定
自定义组件需要双向绑定即实现ControlValueAccessor的接口即可
组件需要继承 ControlValueAccessor
<fl-calendar [(ngModel)]=“value" ><fl-calendar/>
import { ControlValueAccessor } from '@angular/forms';
import { Component, OnInit, Input, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
export const CALENDAR_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Calendar),
multi: true
};
@Component({
selector: 'fl-calendar',
templateUrl: './calendar.component.html',
styleUrls: [‘./calendar.component.scss'],
providers: [CALENDAR_VALUE_ACCESSOR]
})
export class CalendarComponent implements OnInit, ControlValueAccessor {
constructor() { }
private innerValue: any = '';
public onModelChange: Function = () => {};
public onModelTouched: Function = () => {};
ngOnInit() {}
set value(v: any) {
if (v !== this.innerValue) {
this.innerValue = v;
this.onModelChange(v); // value更改
}
}
get value(): any {
return this.innerValue;
}
// 获取value值 组件使用 值未改变时,不触发writeValue方法
writeValue(value: any) {
if (value !== this.innerValue) {
this.innerValue = value;
}
}
registerOnChange(fn: any) {
this.onModelChange = fn;
}
registerOnTouched(fn: any) {
this.onModelTouched = fn;
}
}
https://serious-lose.notion.site/NG-Model-89fca26e60784903b9b16a7c5b52bdb5