ng2-диаграмма обновляется только тогда, когда курсор находится в определенной позиции

У меня есть страница в моем веб-приложении angular2, где я показываю список элементов. Рядом с ним находится боковое меню.
Когда выбран один из элементов в списке, я показываю дополнительное подробное представление, включающее лепестковую диаграмму (используя библиотека ng2-charts), которая привязывается к массиву данных. Поскольку я извлекаю данные, которые хочу отобразить, из базы данных, массив инициализируется с использованием некоторых данных по умолчанию, а затем обновляется с помощью наблюдаемого:

public spiderChartData:any = [
    {label: "",fill:false, scaleShowLabels : false, borderWidth:5, 
    fillColor: "rgba(220,220,220,0.2)",
   data: [30,30,30,30,30]}
];
constructor(private fs : FirebaseService) { }
ngAfterViewInit() {
    this.fs.getWorkoutRatings(this.wName).valueChanges().subscribe(res => {
        this.ratings = res.map(x=>x);
        console.log("data received");
        this.spiderChartData = [
            {label: "",fill:false, scaleShowLabels : false, borderWidth:5, 
            fillColor: "rgba(220,220,220,0.2)",
            data: this.ratings;
    });

}

По логу вижу, что нужные данные приходят практически моментально. Однако по какой-то причине диаграмма не перерисовывается, пока я не наведу курсор на боковое меню; затем диаграмма обновляется мгновенно.
Я хочу, чтобы диаграмма обновлялась, как только будут получены новые данные.
Я пытался обновить диаграмму вручную или даже уничтожить и перерисовать ее, но пока ничего не решило эту проблему.


Дополнительная информация

соответствующий HTML:

<canvas baseChart
    [datasets]="spiderChartData"
    [labels]="spiderChartLabels"
    [chartType]="spiderChartType"
    [options]="spiderChartOptions"
    [colors]="spiderChartColours"
    (chartHover)="chartHovered($event)"
    (chartClick)="chartClicked($event)">
</canvas>
  • Я в значительной степени скопировал весь код для диаграммы из другого, гораздо более простого проекта, который представлял собой всего одну страницу, показывающую эту диаграмму. Там автоматическое обновление работало без проблем.
  • У меня возникли проблемы с выделением минимального рабочего примера для демонстрации, но я все равно надеюсь, что кто-нибудь сможет мне помочь.

person Athos    schedule 17.05.2018    source источник


Ответы (1)


Это происходит потому, что ваш массив spiderChartData остается таким же, как при обнаружении изменений Angular. Я имею в виду, что ссылка не изменяет только свойство data внутри.

Angular в отличие от AngularJS не выполняет грязную проверку на изменение значения; он сравнивает переменные, используя === вместо ==.

Итак, чтобы Angular запускал обнаружение изменений, используйте:

    public spiderChartData:any = []; //<--- initialize as empty array to begin with

    constructor(private fs : FirebaseService) { }
    ngAfterViewInit() {
        this.fs.getWorkoutRatings(this.wName).valueChanges().subscribe(res => {
            this.ratings = res.map(x=>x);
            console.log("data received");
            this.spiderChartData = [
                {label: "",fill:false, scaleShowLabels : false, borderWidth:5, 
                fillColor: "rgba(220,220,220,0.2)",
                data: this.ratings;
        });
   }

OR

Если вы не хотите инициализировать массив как пустой, вам нужно вызвать ChangeDetectorRef.detectChange() в ngAfterViewInit, поэтому явно сообщите Angular, чтобы запустить цикл обнаружения изменений.

public spiderChartData:any = [
    {label: "",fill:false, scaleShowLabels : false, borderWidth:5, 
    fillColor: "rgba(220,220,220,0.2)",
   data: [30,30,30,30,30]}
];

 constructor(private fs : FirebaseService
      private _cdRef : ChangeDetectorRef//<--- inject ChangeDetectorRef
      ) { }

    ngAfterViewInit() {
        this.fs.getWorkoutRatings(this.wName).valueChanges().subscribe(res => {
            this.ratings = res.map(x=>x);
            console.log("data received");
            this.spiderChartData = [
                {label: "",fill:false, scaleShowLabels : false, borderWidth:5, 
                fillColor: "rgba(220,220,220,0.2)",
                data: this.ratings;
        });
    this._cdRef.detectChanges(); // <-- tell angular to run cd for this components and it's siblings
       }
person candidJ    schedule 17.05.2018
comment
Спасибо друг. Это работает для меня. Я изменил ChangeDetectionRef во втором решении на ChangeDetectorRef; Подозреваю, что это была просто опечатка. - person Athos; 17.05.2018
comment
@deadpool добро пожаловать. Я тоже исправил опечатку :) - person candidJ; 17.05.2018