Skip to content

Commit

Permalink
fix(carousel): do change detection when slides change
Browse files Browse the repository at this point in the history
Closes #2908
Fixes #2900
  • Loading branch information
maxokorokov committed Dec 6, 2018
1 parent 8d5397c commit a944d5d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 12 deletions.
40 changes: 31 additions & 9 deletions src/carousel/carousel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ describe('ngb-carousel', () => {
discardPeriodicTasks();
}));

it('should mark component for check for API calls', fakeAsync(() => {
const html = `
it('should mark component for check for API calls', () => {
const html = `
<ngb-carousel #c [interval]="0">
<ng-template ngbSlide>foo</ng-template>
<ng-template ngbSlide>bar</ng-template>
Expand All @@ -203,15 +203,36 @@ describe('ngb-carousel', () => {
<button id="next" (click)="c.next(); addNewSlide = true">Next</button>
`;

const fixture = createTestComponent(html);
const next = fixture.nativeElement.querySelector('#next');
const fixture = createTestComponent(html);
const next = fixture.nativeElement.querySelector('#next');

expectActiveSlides(fixture.nativeElement, [true, false]);
expectActiveSlides(fixture.nativeElement, [true, false]);

next.click();
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true, false]);
}));
next.click();
fixture.detectChanges();
expectActiveSlides(fixture.nativeElement, [false, true, false]);
});

it('should mark component for check when slides change', () => {
const html = `
<ngb-carousel #c [interval]="0">
<ng-template ngbSlide *ngFor="let s of slides">
<div class="slide">{{ s }}</div>
</ng-template>
</ngb-carousel>
`;

function getSlidesText(element: HTMLElement): string[] {
return Array.from(element.querySelectorAll('.carousel-item .slide')).map((el: HTMLElement) => el.innerHTML);
}

const fixture = createTestComponent(html);
expect(getSlidesText(fixture.nativeElement)).toEqual(['a', 'b']);

fixture.componentInstance.slides = ['c', 'd'];
fixture.detectChanges();
expect(getSlidesText(fixture.nativeElement)).toEqual(['c', 'd']);
});

it('should change slide on indicator click', fakeAsync(() => {
const html = `
Expand Down Expand Up @@ -737,6 +758,7 @@ class TestComponent {
pauseOnHover = true;
showNavigationArrows = true;
showNavigationIndicators = true;
slides = ['a', 'b'];
carouselSlideCallBack = (event: NgbSlideEvent) => {};
}

Expand Down
9 changes: 6 additions & 3 deletions src/carousel/carousel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {isPlatformBrowser} from '@angular/common';

import {NgbCarouselConfig} from './carousel-config';

import {Subject, timer} from 'rxjs';
import {merge, Subject, timer} from 'rxjs';
import {filter, map, switchMap, takeUntil} from 'rxjs/operators';

let nextId = 0;
Expand Down Expand Up @@ -79,6 +79,7 @@ export class NgbCarousel implements AfterContentChecked,
AfterContentInit, OnChanges, OnDestroy {
@ContentChildren(NgbSlide) slides: QueryList<NgbSlide>;

private _destroy$ = new Subject<void>();
private _start$ = new Subject<void>();
private _stop$ = new Subject<void>();

Expand Down Expand Up @@ -146,20 +147,22 @@ export class NgbCarousel implements AfterContentChecked,
this._start$
.pipe(
map(() => this.interval), filter(interval => interval > 0 && this.slides.length > 0),
switchMap(interval => timer(interval).pipe(takeUntil(this._stop$))))
switchMap(interval => timer(interval).pipe(takeUntil(merge(this._stop$, this._destroy$)))))
.subscribe(() => this._ngZone.run(() => this.next()));

this._start$.next();
});
}

this.slides.changes.pipe(takeUntil(this._destroy$)).subscribe(() => this._cd.markForCheck());
}

ngAfterContentChecked() {
let activeSlide = this._getSlideById(this.activeId);
this.activeId = activeSlide ? activeSlide.id : (this.slides.length ? this.slides.first.id : null);
}

ngOnDestroy() { this._stop$.next(); }
ngOnDestroy() { this._destroy$.next(); }

ngOnChanges(changes) {
if ('interval' in changes && !changes['interval'].isFirstChange()) {
Expand Down

0 comments on commit a944d5d

Please sign in to comment.