Angular cdk scrolling:更新数据源未显示在视图中
Angular cdk scrolling: Updating Data Source not represented in view
到目前为止,我之前构建无限滚动条的所有尝试都失败了。
我目前正在处理的组件使用 Angular 的虚拟滚动,并且应该在达到虚拟滚动视口的某个索引时更新数据源。
虽然 BehaviorSubject 确实得到了更新,但我在视图中看不到新版本。
我的组件如下所示:
import {Day, Month, Selected, Weekday} from './datepicker';
import {CdkVirtualScrollViewport} from '@angular/cdk/scrolling';
import {BehaviorSubject} from 'rxjs';
@Component({
selector: 'app-calendar-datepicker',
templateUrl: './calendar-datepicker.component.html',
styleUrls: ['./calendar-datepicker.component.scss']
})
export class CalendarDatepickerComponent implements OnInit {
months: BehaviorSubject<any[]> = new BehaviorSubject<any[]>([]);
previousScrollIndex: number;
@ViewChild('dateScroller') dateScroller: CdkVirtualScrollViewport;
constructor() {
}
ngOnInit() {
/*initialization of the array*/
const initialMonths = [];
const month = new Month(this.currentDate);
const date = moment(this.currentDate);
const nextMonth = new Month(date.add(1, 'M'));
const nextDate = moment(date);
const monthAfterNextMonth = new Month(nextDate.add(1, 'M'));
initialMonths.push(month);
initialMonths.push(nextMonth);
initialMonths.push(monthAfterNextMonth);
this.months.next(initialMonths);
}
public onScroll(index) {
if (typeof(this.previousScrollIndex) === 'undefined') {
this.previousScrollIndex = index;
} else if (this.previousScrollIndex < index) {
if (index % 2 === 0) {
this.dateScroller.scrollToIndex(index);
} else {
this.dateScroller.scrollToIndex(index + 1);
/*This is the place where the BehaviorSubject is updated*/
const date = moment(this.months.value[index].date);
const monthToFetch = new Month(date.add(2, 'M'));
const fetchedMonths = this.months.value;
fetchedMonths.push(monthToFetch);
this.months.next(fetchedMonths);
}
this.previousScrollIndex = index;
} else {
if (index % 2 === 0) {
this.dateScroller.scrollToIndex(index);
} else {
this.dateScroller.scrollToIndex(index - 1);
}
this.previousScrollIndex = index;
}
}
}
并且视图如下:
<cdk-virtual-scroll-viewport itemSize="92" #dateScroller class="scroll-container"
(scrolledIndexChange)="onScroll($event)">
<div *cdkVirtualFor="let month of months | async">
<div class="month">{{month.date.format('MMMM')}}</div>
<div class="days">
<div class="day previousMonth" *ngFor="let prevMonthDay of month.prevMonthDays"></div>
<div class="day" *ngFor="let day of month.monthDays" (click)="onSelect(day)"
[ngClass]="{ 'selected': day.selected, 'past': day.past, 'today': day.today,
'first': day.firstSelected && isRangeSelected, 'last':day.lastSelected,
'onlyOneSelected': day.firstSelected && !isRangeSelected}">
<span *ngIf="day.firstSelected || day.lastSelected" class="borderDay"></span>
<span class="dayText">{{day.number}}</span>
</div>
</div>
</div>
</cdk-virtual-scroll-viewport>
到目前为止,我已尝试使用 ChangeDetectorRef 并手动触发它或将我的代码放入 setTimeout()
函数中以更新 months
,但都没有用。
我认为你的问题是你将新的月份附加到同一个数组,所以对象引用没有改变。因此,Angular 认为不需要重新呈现数据。
尝试:
const fetchedMonths = [...this.months.value, monthToFetch]
到目前为止,我之前构建无限滚动条的所有尝试都失败了。 我目前正在处理的组件使用 Angular 的虚拟滚动,并且应该在达到虚拟滚动视口的某个索引时更新数据源。 虽然 BehaviorSubject 确实得到了更新,但我在视图中看不到新版本。
我的组件如下所示:
import {Day, Month, Selected, Weekday} from './datepicker';
import {CdkVirtualScrollViewport} from '@angular/cdk/scrolling';
import {BehaviorSubject} from 'rxjs';
@Component({
selector: 'app-calendar-datepicker',
templateUrl: './calendar-datepicker.component.html',
styleUrls: ['./calendar-datepicker.component.scss']
})
export class CalendarDatepickerComponent implements OnInit {
months: BehaviorSubject<any[]> = new BehaviorSubject<any[]>([]);
previousScrollIndex: number;
@ViewChild('dateScroller') dateScroller: CdkVirtualScrollViewport;
constructor() {
}
ngOnInit() {
/*initialization of the array*/
const initialMonths = [];
const month = new Month(this.currentDate);
const date = moment(this.currentDate);
const nextMonth = new Month(date.add(1, 'M'));
const nextDate = moment(date);
const monthAfterNextMonth = new Month(nextDate.add(1, 'M'));
initialMonths.push(month);
initialMonths.push(nextMonth);
initialMonths.push(monthAfterNextMonth);
this.months.next(initialMonths);
}
public onScroll(index) {
if (typeof(this.previousScrollIndex) === 'undefined') {
this.previousScrollIndex = index;
} else if (this.previousScrollIndex < index) {
if (index % 2 === 0) {
this.dateScroller.scrollToIndex(index);
} else {
this.dateScroller.scrollToIndex(index + 1);
/*This is the place where the BehaviorSubject is updated*/
const date = moment(this.months.value[index].date);
const monthToFetch = new Month(date.add(2, 'M'));
const fetchedMonths = this.months.value;
fetchedMonths.push(monthToFetch);
this.months.next(fetchedMonths);
}
this.previousScrollIndex = index;
} else {
if (index % 2 === 0) {
this.dateScroller.scrollToIndex(index);
} else {
this.dateScroller.scrollToIndex(index - 1);
}
this.previousScrollIndex = index;
}
}
}
并且视图如下:
<cdk-virtual-scroll-viewport itemSize="92" #dateScroller class="scroll-container"
(scrolledIndexChange)="onScroll($event)">
<div *cdkVirtualFor="let month of months | async">
<div class="month">{{month.date.format('MMMM')}}</div>
<div class="days">
<div class="day previousMonth" *ngFor="let prevMonthDay of month.prevMonthDays"></div>
<div class="day" *ngFor="let day of month.monthDays" (click)="onSelect(day)"
[ngClass]="{ 'selected': day.selected, 'past': day.past, 'today': day.today,
'first': day.firstSelected && isRangeSelected, 'last':day.lastSelected,
'onlyOneSelected': day.firstSelected && !isRangeSelected}">
<span *ngIf="day.firstSelected || day.lastSelected" class="borderDay"></span>
<span class="dayText">{{day.number}}</span>
</div>
</div>
</div>
</cdk-virtual-scroll-viewport>
到目前为止,我已尝试使用 ChangeDetectorRef 并手动触发它或将我的代码放入 setTimeout()
函数中以更新 months
,但都没有用。
我认为你的问题是你将新的月份附加到同一个数组,所以对象引用没有改变。因此,Angular 认为不需要重新呈现数据。
尝试:
const fetchedMonths = [...this.months.value, monthToFetch]