Skip to content

Commit

Permalink
feat(carousel): add flags controling display of navigation arrows and…
Browse files Browse the repository at this point in the history
… indicators

Closes #2274
Closes #2275
  • Loading branch information
wilhelmhb authored and pkozlowski-opensource committed Jun 22, 2018
1 parent 7eaa7e7 commit ec4e939
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 9 deletions.
3 changes: 3 additions & 0 deletions demo/src/app/components/carousel/carousel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {DEMO_SNIPPETS} from './demos';
<ngbd-example-box demoTitle="Carousel" [snippets]="snippets" component="carousel" demo="basic">
<ngbd-carousel-basic></ngbd-carousel-basic>
</ngbd-example-box>
<ngbd-example-box demoTitle="Navigation arrows and indicators" [snippets]="snippets" component="carousel" demo="navigation">
<ngbd-carousel-navigation></ngbd-carousel-navigation>
</ngbd-example-box>
<ngbd-example-box demoTitle="Global configuration of carousels" [snippets]="snippets" component="carousel" demo="config">
<ngbd-carousel-config></ngbd-carousel-config>
</ngbd-example-box>
Expand Down
7 changes: 6 additions & 1 deletion demo/src/app/components/carousel/demos/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {NgbdCarouselBasic} from './basic/carousel-basic';
import {NgbdCarouselConfig} from './config/carousel-config';
import {NgbdCarouselNavigation} from './navigation/carousel-navigation';

export const DEMO_DIRECTIVES = [NgbdCarouselBasic, NgbdCarouselConfig];
export const DEMO_DIRECTIVES = [NgbdCarouselBasic, NgbdCarouselConfig, NgbdCarouselNavigation];

export const DEMO_SNIPPETS = {
'basic': {
Expand All @@ -11,5 +12,9 @@ export const DEMO_SNIPPETS = {
'config': {
'code': require('!!raw-loader!./config/carousel-config'),
'markup': require('!!raw-loader!./config/carousel-config.html')
},
'navigation': {
'code': require('!!raw-loader!./navigation/carousel-navigation'),
'markup': require('!!raw-loader!./navigation/carousel-navigation.html')
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<ngb-carousel *ngIf="images" [showNavigationArrows]="showNavigationArrows" [showNavigationIndicators]="showNavigationIndicators">
<ng-template ngbSlide *ngFor="let image of images">
<img [src]="image" alt="Random slide">
<div class="carousel-caption">
<h3>No mouse navigation</h3>
<p>This carousel hides navigation arrows and indicators.</p>
</div>
</ng-template>
</ngb-carousel>

<hr>

<div class="btn-group" role="group" aria-label="Carousel toggle controls">
<button type="button" (click)="showNavigationArrows = !showNavigationArrows" class="btn btn-outline-dark btn-sm">Toggle navigation arrows</button>
<button type="button" (click)="showNavigationIndicators = !showNavigationIndicators" class="btn btn-outline-dark btn-sm">Toggle navigation indicators</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {Component, OnInit} from '@angular/core';
import {NgbCarouselConfig} from '@ng-bootstrap/ng-bootstrap';
import {map} from 'rxjs/operators';
import {HttpClient} from '@angular/common/http';

@Component({
selector: 'ngbd-carousel-navigation',
templateUrl: './carousel-navigation.html',
providers: [NgbCarouselConfig] // add NgbCarouselConfig to the component providers
})
export class NgbdCarouselNavigation implements OnInit {
showNavigationArrows = false;
showNavigationIndicators = false;
images: Array<string>;

constructor(config: NgbCarouselConfig, private _http: HttpClient) {
// customize default values of carousels used by this component tree
config.showNavigationArrows = true;
config.showNavigationIndicators = true;
}

ngOnInit() {
this._http.get('https://picsum.photos/list')
.pipe(map((images: Array<{id: number}>) => this._randomImageUrls(images)))
.subscribe(images => this.images = images);
}

private _randomImageUrls(images: Array<{id: number}>): Array<string> {
return [1, 2].map(() => {
const randomId = images[Math.floor(Math.random() * images.length)].id;
return `https://picsum.photos/900/500?image=${randomId}`;
});
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Component, Injectable} from '@angular/core';
import {NgbTimeStruct, NgbTimeAdapter} from '@ng-bootstrap/ng-bootstrap';
import {NgbDateNativeAdapter} from '../../../datepicker/demos/adapter/datepicker-adapter';

/**
* Example of a String Time adapter
Expand Down
2 changes: 2 additions & 0 deletions src/carousel/carousel-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@ describe('ngb-carousel-config', () => {
expect(config.keyboard).toBe(true);
expect(config.wrap).toBe(true);
expect(config.pauseOnHover).toBe(true);
expect(config.showNavigationIndicators).toBe(true);
expect(config.showNavigationArrows).toBe(true);
});
});
2 changes: 2 additions & 0 deletions src/carousel/carousel-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ export class NgbCarouselConfig {
wrap = true;
keyboard = true;
pauseOnHover = true;
showNavigationArrows = true;
showNavigationIndicators = true;
}
55 changes: 53 additions & 2 deletions src/carousel/carousel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function expectActiveSlides(nativeEl: HTMLDivElement, active: boolean[]) {
}
}

describe('ngb-carousel', () => {
fdescribe('ngb-carousel', () => {
beforeEach(() => {
TestBed.configureTestingModule({declarations: [TestComponent], imports: [NgbCarouselModule.forRoot()]});
});
Expand All @@ -42,6 +42,8 @@ describe('ngb-carousel', () => {
expect(carousel.wrap).toBe(defaultConfig.wrap);
expect(carousel.keyboard).toBe(defaultConfig.keyboard);
expect(carousel.pauseOnHover).toBe(defaultConfig.pauseOnHover);
expect(carousel.showNavigationIndicators).toBe(defaultConfig.showNavigationIndicators);
expect(carousel.showNavigationArrows).toBe(defaultConfig.showNavigationArrows);
});

it('should render slides and navigation indicators', fakeAsync(() => {
Expand All @@ -59,6 +61,7 @@ describe('ngb-carousel', () => {
expect(slideElms[1].textContent).toMatch(/bar/);

expect(fixture.nativeElement.querySelectorAll('ol.carousel-indicators > li').length).toBe(2);
expect(fixture.nativeElement.querySelectorAll('[role="button"]').length).toBe(2);

discardPeriodicTasks();
}));
Expand Down Expand Up @@ -516,6 +519,45 @@ describe('ngb-carousel', () => {

}));

it('should render navigation indicators according to the flags', fakeAsync(() => {
const html = `
<ngb-carousel [showNavigationIndicators]="showNavigationIndicators">
<ng-template ngbSlide>foo</ng-template>
</ngb-carousel>
`;
const fixture = createTestComponent(html);

const slideElms = fixture.nativeElement.querySelectorAll('.carousel-item');
expect(slideElms.length).toBe(1);
expect(slideElms[0].textContent).toMatch(/foo/);
expect(fixture.nativeElement.querySelectorAll('ol.carousel-indicators > li').length).toBe(1);

fixture.componentInstance.showNavigationIndicators = false;
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('ol.carousel-indicators > li').length).toBe(0);

discardPeriodicTasks();
}));

it('should render navigation buttons according to the flags', fakeAsync(() => {
const html = `
<ngb-carousel [showNavigationArrows]="showNavigationArrows">
<ng-template ngbSlide>foo</ng-template>
</ngb-carousel>
`;
const fixture = createTestComponent(html);

const slideElms = fixture.nativeElement.querySelectorAll('.carousel-item');
expect(slideElms.length).toBe(1);
expect(fixture.nativeElement.querySelectorAll('[role="button"]').length).toBe(2);

fixture.componentInstance.showNavigationArrows = false;
fixture.detectChanges();
expect(fixture.nativeElement.querySelectorAll('[role="button"]').length).toBe(0);

discardPeriodicTasks();
}));

describe('Custom config', () => {
let config: NgbCarouselConfig;

Expand All @@ -527,6 +569,8 @@ describe('ngb-carousel', () => {
config.wrap = false;
config.keyboard = false;
config.pauseOnHover = false;
config.showNavigationIndicators = true;
config.showNavigationArrows = true;
}));

it('should initialize inputs with provided config', () => {
Expand All @@ -538,6 +582,8 @@ describe('ngb-carousel', () => {
expect(carousel.wrap).toBe(config.wrap);
expect(carousel.keyboard).toBe(config.keyboard);
expect(carousel.pauseOnHover).toBe(config.pauseOnHover);
expect(carousel.showNavigationIndicators).toBe(config.showNavigationIndicators);
expect(carousel.showNavigationArrows).toBe(config.showNavigationArrows);
});
});

Expand All @@ -547,7 +593,8 @@ describe('ngb-carousel', () => {
config.wrap = false;
config.keyboard = false;
config.pauseOnHover = false;

config.showNavigationIndicators = true;
config.showNavigationArrows = true;

beforeEach(() => {
TestBed.configureTestingModule(
Expand All @@ -563,6 +610,8 @@ describe('ngb-carousel', () => {
expect(carousel.wrap).toBe(config.wrap);
expect(carousel.keyboard).toBe(config.keyboard);
expect(carousel.pauseOnHover).toBe(config.pauseOnHover);
expect(carousel.showNavigationIndicators).toBe(config.showNavigationIndicators);
expect(carousel.showNavigationArrows).toBe(config.showNavigationArrows);
});
});

Expand All @@ -574,5 +623,7 @@ class TestComponent {
activeSlideId;
keyboard = true;
pauseOnHover = true;
showNavigationArrows = true;
showNavigationIndicators = true;
carouselSlideCallBack = (event: NgbSlideEvent) => {};
}
25 changes: 20 additions & 5 deletions src/carousel/carousel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class NgbSlide {
'(keydown.arrowRight)': 'keyNext()'
},
template: `
<ol class="carousel-indicators">
<ol class="carousel-indicators" *ngIf="showNavigationIndicators">
<li *ngFor="let slide of slides" [id]="slide.id" [class.active]="slide.id === activeId"
(click)="cycleToSelected(slide.id, getSlideEventDirection(activeId, slide.id))"></li>
</ol>
Expand All @@ -54,11 +54,11 @@ export class NgbSlide {
<ng-template [ngTemplateOutlet]="slide.tplRef"></ng-template>
</div>
</div>
<a class="carousel-control-prev" role="button" (click)="cycleToPrev()">
<a class="carousel-control-prev" role="button" (click)="cycleToPrev()" *ngIf="showNavigationArrows">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only" i18n="@@ngb.carousel.previous">Previous</span>
</a>
<a class="carousel-control-next" role="button" (click)="cycleToNext()">
<a class="carousel-control-next" role="button" (click)="cycleToNext()" *ngIf="showNavigationArrows">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only" i18n="@@ngb.carousel.next">Next</span>
</a>
Expand All @@ -69,6 +69,12 @@ export class NgbCarousel implements AfterContentChecked,
@ContentChildren(NgbSlide) slides: QueryList<NgbSlide>;
private _slideChangeInterval;

/**
* The active slide id.
*/
@Input() activeId: string;


/**
* Amount of time in milliseconds before next slide is shown.
*/
Expand All @@ -91,9 +97,16 @@ export class NgbCarousel implements AfterContentChecked,
@Input() pauseOnHover: boolean;

/**
* The active slide id.
* A flag to show / hide navigation arrows.
* @since 2.2.0
*/
@Input() activeId: string;
@Input() showNavigationArrows: boolean;

/**
* A flag to show / hide navigation indicators.
* @since 2.2.0
*/
@Input() showNavigationIndicators: boolean;

/**
* A carousel slide event fired when the slide transition is completed.
Expand All @@ -106,6 +119,8 @@ export class NgbCarousel implements AfterContentChecked,
this.wrap = config.wrap;
this.keyboard = config.keyboard;
this.pauseOnHover = config.pauseOnHover;
this.showNavigationArrows = config.showNavigationArrows;
this.showNavigationIndicators = config.showNavigationIndicators;
}

ngAfterContentChecked() {
Expand Down

0 comments on commit ec4e939

Please sign in to comment.