uiuniversal / ngu-carousel

Angular Universal carousel
https://ngu-carousel.netlify.app
MIT License
328 stars 104 forks source link

ExpressionChangedAfterItHasBeenCheckedError for custom points #83

Open mikitabut opened 5 years ago

mikitabut commented 5 years ago

Get this error, while using nguCarousel custom points: ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngForOf: '. Current value: 'ngForOf: 0,1'. The same error you can see in official sandbox. What you think about this?

sheikalthaf commented 5 years ago

@weterbogov Hi,

It is not an error. This message occurs when the data changed on change detection happens. This will be removed on production build. Will fix this later

Thanks

angelserranoperez commented 5 years ago

source => https://stackoverflow.com/questions/43375532/expressionchangedafterithasbeencheckederror-explained

I workaround this issue with that:

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush
    selector: -
    ......
})
sheikalthaf commented 5 years ago

@weterbogov @angelserranoperez Also detectChanges,

import { Component, OnInit, ChangeDetectionStrategy, AfterViewInit, ChangeDetectorRef} from '@angular/core';

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush
    selector: -
    ......
})
export class AppComponent Implements AfterViewInit {
   constructor(private cdr: ChangeDetectorRef) {}

   ngAfterViewInit() {
    // this is used to renderer the carousel changes
     this.cdr.detectChanges();
   }
}
corentin-gautier commented 5 years ago

@sheikalthaf any ETA on this ? It Makes the carousel unusable (I can't change the changeDetection strategy, it breaks everything else in my app)

eyalhakim commented 5 years ago

I really need this fixed

kmturley commented 5 years ago

I think it's an async issue with the data updating after the bindings. I solved using an onMove function to update controller variables so the variables always stay consistent with values:

<ngu-carousel #myCarousel [inputs]="carouselTile" [dataSource]="page.images" class="carousel" (onMove)="onCarouselMove($event)">
  <ngu-tile *nguCarouselDef="let image; let i = index">
    <div class="carousel-item">
        <img [src]="image" alt="Image" draggable="false" />
    </div>
  </ngu-tile>
  <button NguCarouselPrev class="carousel-arrow carousel-arrow-left" [disabled]="leftNavDisabled">&lt;</button>
  <button NguCarouselNext class="carousel-arrow carousel-arrow-right" [disabled]="rightNavDisabled">&gt;</button>
  <ul class="carousel-indicators" NguCarouselPoint [hidden]="points.length==0">
    <li *ngFor="let i of points; let i = index" [class.active]="i==myCarousel.activePoint" (click)="myCarousel.moveTo(i)"></li>
  </ul>
</ngu-carousel>

And then the controller:

@ViewChild('myCarousel') myCarousel: NguCarousel<any>;
leftNavDisabled = false;
rightNavDisabled = false;
points = [];

onCarouselMove() {
  if (this.myCarousel.pointNumbers) {
    this.points = this.myCarousel.pointNumbers;
  } else {
    this.points = [];
  }
  if (this.myCarousel.isFirst) {
    this.leftNavDisabled = true;
  } else {
    this.leftNavDisabled = false;
  }
  if (this.myCarousel.isLast) {
    this.rightNavDisabled = true;
  } else {
    this.rightNavDisabled = false;
  }
}
FingalP commented 5 years ago

We had the same problem, and we tried fixing it with the solution from @kmturley (thanks!) but we also needed to have the points set when the carousel was created, which we got around by using a setter on the view child:

On the component:


@ViewChild('myCarousel')
set _myCarousel(myCarousel: NguCarousel) {
    this.myCarousel = myCarousel;
    setTimeout(() => {
        this.points = myCarousel.pointNumbers;
    });
}

carouselIsFirst = true;
carouselIsLast = false;
points: any[] = [];

onCarouselMove(myCarousel: NguCarousel) {
    this.carouselIsFirst = myCarousel.isFirst;
    this.carouselIsLast = myCarousel.isLast;
    if (myCarousel.pointNumbers) {
        this.points = myCarousel.pointNumbers;
    } else {
        this.points = [];
    }
}

and in the html:

<ngu-carousel #myCarousel class="carousel" [inputs]="carouselTile" [dataSource]="dataSource" (onMove)="onCarouselMove($event)">

cqduydev commented 4 years ago

Thanks for making awesome carousel for me and Angular community. But please fix it, I know it's not a critical one but in Angular 9 if this error happens debugger will call every time we recompile app .... It's annoying.

santoshyadavdev commented 4 years ago

Hey @cqduydev, Sure I recently started managing this, will take care of this bug in next release.

Parsa-Sedigh commented 3 years ago

@santoshyadavdev Any updates on this issue?

TobiasJu commented 3 months ago

Hey @santoshyadavdev you got an update for us yet?