From 25fd9102a2003ce5012093e3c3a1a4a1d8a6c186 Mon Sep 17 00:00:00 2001 From: "kirill.chirkov@home" Date: Thu, 6 Feb 2020 23:16:11 +0300 Subject: [PATCH] fix: postpone setIndex when no slides available --- README.md | 2 +- .../lib/private/service/carousel.service.ts | 22 +++++++++++++++++-- .../service/helpers/find-slide-index.spec.ts | 4 ++++ .../service/helpers/find-slide-index.ts | 11 +++++++++- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 44ddcf0..58570b2 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ or Use this reference to programmaticaly trigger next events: - `carouselRef.next()`: increment active slide - `carouselRef.prev()`: decrement active slide -- `carouselRef.setIndex(newIndex: number)`: focus slide with provided item index +- `carouselRef.setIndex(newIndex: number)`: focus slide with provided item index. When no slides are available, index change would postpone till slide initialization. - `carouselRef.recalculate()`: recalculate positions ### PreventGhostClickDirective diff --git a/projects/ng-carousel/src/lib/private/service/carousel.service.ts b/projects/ng-carousel/src/lib/private/service/carousel.service.ts index 92b42e8..66a918a 100644 --- a/projects/ng-carousel/src/lib/private/service/carousel.service.ts +++ b/projects/ng-carousel/src/lib/private/service/carousel.service.ts @@ -50,6 +50,11 @@ export class CarouselService implements OnDestroy { private readonly carouselState$ = new BehaviorSubject(new CarouselState()); private readonly destroyed$ = new Subject(); private currentAnimationId: number | null = null; + /** + * Item index that should be applied when carousel slides + * are initialized first time + */ + private postponedItemIndex: number; constructor( private animation: AnimationBuilder, @@ -70,8 +75,13 @@ export class CarouselService implements OnDestroy { } setItemIndex(newItemIndex: number): void { - this.enableAutoplay(); // Reset timer on programmatic item index change const carouselState = this.cloneCarouselState(); + if (!carouselState.slides.length) { + this.postponedItemIndex = newItemIndex; + + return; + } + this.enableAutoplay(); // Reset timer on programmatic item index change const slideIndex = findSlideIndex( carouselState.slides, newItemIndex, @@ -326,7 +336,7 @@ export class CarouselService implements OnDestroy { /** * Narrow case scenario helper: use this when carousel inputs change. - * Function task is to initialize carousel whether all the components + * Function task is to initialize carousel when all the components * are ready. */ private applyStateChange(newState: CarouselState): void { @@ -348,6 +358,14 @@ export class CarouselService implements OnDestroy { || currentState.config.items !== newState.config.items ) { newState = this.initializeCarousel(newState); + this.setCarouselState(newState); + + if (newState.slides.length && this.postponedItemIndex) { + this.setItemIndex(this.postponedItemIndex); + this.postponedItemIndex = null; + } + + return; } this.setCarouselState(newState); } diff --git a/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.spec.ts b/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.spec.ts index a557deb..cd6d76b 100644 --- a/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.spec.ts +++ b/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.spec.ts @@ -83,4 +83,8 @@ describe('findItemIndex test suite', () => { )).toThrowError(CarouselError); }); + it('must return 0 when no slides available', () => { + expect(findSlideIndex([], 10, 10)).toBe(0); + expect(findSlideIndex(null, 10, 10)).toBe(0); + }); }); diff --git a/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.ts b/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.ts index 2febed5..582c65c 100644 --- a/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.ts +++ b/projects/ng-carousel/src/lib/private/service/helpers/find-slide-index.ts @@ -11,7 +11,16 @@ export function findSlideIndex( newItemIndex: number, currentSlideIndex: number, ): number { - const currentItemIndex = slides[currentSlideIndex].itemIndex; + if (!slides) { + + return 0; + } + const currentActiveSlide = slides[currentSlideIndex]; + if (!currentActiveSlide) { + + return 0; + } + const currentItemIndex = currentActiveSlide.itemIndex; let targetSlideIndex: IterateSideResult | null = null; if (newItemIndex === currentItemIndex || slides.length <= 1) {