正在为ng-bootstrap开发一些自定义包装器。这个问题的想法是创建一个以Date作为其[ngModel]的组件。
我注意到我的包装器在我正在处理的应用程序中实现它的一个错误,它需要同一个对象的多个组件,但在同一页面上有不同的引用。似乎如果我创建了两个应引用相同对象的变量,它们实际上彼此不同步。例如:
this.date: Date = new Date();
this.copy: Date = date;
....
<my-component [ngModel]="date"></my-component>
<my-component [ngModel]="copy"></my-component>
<-- Components don't stay in sync - date and copy point at different Dates -->
我理解这是因为我的ControlValueAccessor实现有问题。不知何故,我覆盖了引用以指向新的Date对象而不是修改给定的对象。
我认为这是由我的捡拾器上的56号线引起的?但也可能与ControlValueAccessor有关,我没有正确地理解/理解。看起来像调整我的Date对象以匹配包装的NgbDatePicker的NgbDateStruct通过DoCheck生命周期钩子有点hacky(虽然我不认为它导致问题 - 更喜欢一个聪明的RxJS解决方案,但还没有想到一个。)
我的应用代码:
@Component({
selector: 'my-app',
template: `
<h1>
{{title}}
</h1>
<hr>
<h2>Day Picker</h2>
<app-day-picker [(ngModel)]="dayPickerDay"></app-day-picker>
Day: {{ dayPickerDay | date:mediumDate }}
<br>
<button (click)="setToYesterday()">Change to yesterday</button>
<button (click)="setToTomorrow()">Change to tomorrow</button>
<hr>
<h2>Day Picker for copy (should stay in sync... doesn't.</h2>
<app-day-picker [(ngModel)]="dayPickerCopy"></app-day-picker>
Day: {{ dayPickerCopy | date:mediumDate }}
<br>`
})
export class App {
title = 'My time components';
dayPickerDay: Date;
dayPickerCopy: Date;
ngOnInit(){
this.dayPickerDay = new Date(Date.now());
this.dayPickerCopy = this.dayPickerDay;
}
setToTomorrow(){
this.dayPickerDay = new Date(Date.now() + 24*1000*60*60);
}
setToYesterday(){
this.dayPickerDay = new Date(Date.now() - 24*1000*60*60);
}
}
我的包装代码:
const noop = () => {};
export const DAY_PICKER_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DayPickerComponent),
multi: true
};
@Component({
selector: 'app-day-picker',
template: `
<form class="form-inline">
<div class="form-group">
<div class="input-group">
<input class="form-control" placeholder="Select a Date..."
name="dp" [(ngModel)]="dayObject" ngbDatepicker #d="ngbDatepicker" disabled="">
<button class="input-group-addon" (click)="d.toggle()" type="button">
<i class="fa fa-calendar" style="width: 1.2rem; height: 1rem; cursor: pointer;"></i>
</button>
</div>
</div>
</form>
`,
providers: [
DAY_PICKER_CONTROL_VALUE_ACCESSOR
]
})
export class DayPickerComponent implements ControlValueAccessor, DoCheck {
private innerValue: Date = new Date(Date.now());
private dayObject: {year: number, month: number, day: number};
private onTouchedCallback: () => void = noop;
private onChangedCallback: (_: any) => void = noop;
get value(): Date {
return this.innerValue;
}
set value(v: Date){
if(v.getTime() !== this.innerValue.getTime()){
this.innerValue = v;
let years = this.innerValue.getFullYear();
let months = this.innerValue.getMonth() + 1;
let days = this.innerValue.getDate();
this.dayObject = {year: years, month: months, day: days};
this.onChangedCallback(v);
}
}
writeValue(value: Date){
if(value === null) {
value = new Date(Date.now());
}
if(value.getTime() !== this.innerValue.getTime()){
this.innerValue = value;
let years = this.innerValue.getFullYear();
let months = this.innerValue.getMonth() + 1;
let days = this.innerValue.getDate();
this.dayObject = {year: years, month: months, day: days};
}
}
registerOnChange(fn: (_: any) => void): void{
this.onChangedCallback = fn;
}
registerOnTouched(fn: any){
this.onTouchedCallback = fn;
}
ngDoCheck() {
if (this.dayObject) {
this.value.setFullYear(this.dayObject.year, this.dayObject.month - 1, this.dayObject.day);
}
}
}
答案 0 :(得分:0)
问题出在以下代码中:
writeValue(value: Date){
if(value === null) {
value = new Date(Date.now());
}
if(value.getTime() !== this.innerValue.getTime()){
this.innerValue = value; //<-- Right here
let years = this.innerValue.getFullYear();
let months = this.innerValue.getMonth() + 1;
let days = this.innerValue.getDate();
this.dayObject = {year: years, month: months, day: days};
}
}
您正在将this.innervalue
分配给通过引用传递的确切对象!因此,当您执行if(v.getTime() !== this.innerValue.getTime())
时,它将始终相等,因为它是完全相同的Date对象。要纠正所有问题,只需执行以下操作:
this.innerValue = new Date(value);
创建副本。