Skip to content

Commit

Permalink
feat(module:carousel): support custom strategies (#3501)
Browse files Browse the repository at this point in the history
* feat(module:cascader): support custom strategies

* docs: add docs

* test: add test

* docs: fix typo

* fix: fix test and tsconfig
  • Loading branch information
Wendell authored and wenqi73 committed Jun 5, 2019
1 parent 7c0e30c commit a53a43a
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 50 deletions.
21 changes: 15 additions & 6 deletions components/carousel/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,28 @@ import { NzCarouselModule } from 'ng-zorro-antd';
| -------- | ----------- | ---- | ------- |
| `[nzAutoPlay]` | Whether to scroll automatically | `boolean` | `false` |
| `[nzAutoPlaySpeed]` | Duration (milliseconds), does not scroll when set to 0 | `number` | `3000` |
| `[nzDots]` | Whether to show the dots at the bottom of the gallery | `boolean` | `true` |
| `[nzDotRender]` | Dot render template | `TemplateRef<{ $implicit: number }>` | - |
| `[nzEffect]` | Transition effect | `'scrollx'|'fade'` | `'scrollx'` |
| `[nzDots]` | Whether to show the dots at the bottom of the gallery | `boolean` | `true` |
| `[nzEffect]` | Transition effect | `'scrollx'\|'fade'` | `'scrollx'` |
| `[nzEnableSwipe]` | Whether to support swipe gesture | `boolean` | `true` |
| `[nzVertical]` | Whether to use a vertical display | `boolean` | `false` |
| `(nzAfterChange)` | Callback function called after the current index changes | `EventEmitter<number>` | - |
| `(nzBeforeChange)` | Callback function called before the current index changes | `EventEmitter{ from: number; to: number }>` | - |
| `[nzEnableSwipe]` | Whether to support swipe gesture | `boolean` | `true` |

#### Methods

| Name | Description |
| ---- | ----------- |
| goTo(slideNumber) | Change current slide to given slide number |
| next() | Change current slide to next slide |
| pre() | Change current slide to previous slide |
| `goTo(slideNumber)` | Change current slide to given slide number |
| `next()` | Change current slide to next slide |
| `pre()` | Change current slide to previous slide |

### InjectionToken

| Token | Description | Parameters | Default Value |
| ----- | --- | ---- | --- |
| `NZ_CAROUSEL_CUSTOM_STRATEGIES` | Provide custom transitioning strategies | `CarouselStrategyRegistryItem[]` | - |

### Customizing transition effects

From version `7.5.0`, you can provide strategies that extends `NzCarouselBaseStrategy` to implement custom transition effects.
22 changes: 16 additions & 6 deletions components/carousel/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,28 @@ import { NzCarouselModule } from 'ng-zorro-antd';
| --- | --- | --- | --- |
| `[nzAutoPlay]` | 是否自动切换 | `boolean` | `false` |
| `[nzAutoPlaySpeed]` | 切换时间(毫秒),当设置为0时不切换 | `number` | `3000` |
| `[nzDots]` | 是否显示面板指示点 | `boolean` | `true` |
| `[nzDotRender]` | Dot渲染模板 | `TemplateRef<{ $implicit: number }>` | - |
| `[nzEffect]` | 动画效果函数,可取 scrollx, fade | `'scrollx'|'fade'` | `'scrollx'` |
| `[nzDots]` | 是否显示面板指示点 | `boolean` | `true` |
| `[nzEffect]` | 动画效果函数,可取 `scrollx`, `fade` | `'scrollx'\|'fade'`|`'scrollx'` |
| `[nzEnableSwipe]` | 是否支持手势划动切换 | `boolean` | `true` |
| `[nzVertical]` | 垂直显示 | `boolean` | `false` |
| `(nzAfterChange)` | 切换面板的回调 | `EventEmitter<number>` | - |
| `(nzBeforeChange)` | 切换面板的回调 | `EventEmitter<{ from: number; to: number }>` | - |
| `[nzEnableSwipe]` | 是否支持手势划动切换 | `boolean` | `true` |

#### 方法

| 名称 | 描述 |
| --- | --- |
| goTo(slideNumber) | 切换到指定面板 |
| next() | 切换到下一面板 |
| pre() | 切换到上一面板 |
| `goTo(slideNumber)` | 切换到指定面板 |
| `next()` | 切换到下一面板 |
| `pre()` | 切换到上一面板 |

### InjectionToken

| Token | 说明 | 参数 | 默认值 |
| ----- | --- | ---- | --- |
| `NZ_CAROUSEL_CUSTOM_STRATEGIES` | 提供用户自定义的切换效果 | `CarouselStrategyRegistryItem[]` | - |

### 自定义切换效果

`7.5.0` 版本开始,你可以提供自定义的切换效果,切换效果应当继承 `NzCarouselBaseStrategy` 类(默认的两种切换效果同样基于该类)。
15 changes: 13 additions & 2 deletions components/carousel/nz-carousel-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/

import { QueryList } from '@angular/core';
import { InjectionToken, QueryList } from '@angular/core';
import { NzCarouselContentDirective } from './nz-carousel-content.directive';
import { NzCarouselBaseStrategy } from './strategies/base-strategy';

export type NzCarouselEffects = 'fade' | 'scrollx';
// Support string for custom transition effect.
export type NzCarouselEffects = 'fade' | 'scrollx' | string;

export interface NzCarouselComponentAsSource {
carouselContents: QueryList<NzCarouselContentDirective>;
Expand All @@ -30,3 +32,12 @@ export interface FromToInterface {
from: number;
to: number;
}

export interface CarouselStrategyRegistryItem {
name: string;
strategy: NzCarouselBaseStrategy;
}

export const NZ_CAROUSEL_CUSTOM_STRATEGIES = new InjectionToken<CarouselStrategyRegistryItem[]>(
'nz-carousel-custom-strategies'
);
20 changes: 18 additions & 2 deletions components/carousel/nz-carousel.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
NgZone,
OnChanges,
OnDestroy,
Optional,
Output,
QueryList,
Renderer2,
Expand All @@ -37,7 +38,13 @@ import { isTouchEvent, InputBoolean, InputNumber } from 'ng-zorro-antd/core';
import { takeUntil, throttleTime } from 'rxjs/operators';

import { NzCarouselContentDirective } from './nz-carousel-content.directive';
import { FromToInterface, NzCarouselEffects, PointerVector } from './nz-carousel-definitions';
import {
CarouselStrategyRegistryItem,
FromToInterface,
NzCarouselEffects,
NZ_CAROUSEL_CUSTOM_STRATEGIES,
PointerVector
} from './nz-carousel-definitions';
import { NzCarouselBaseStrategy } from './strategies/base-strategy';
import { NzCarouselOpacityStrategy } from './strategies/opacity-strategy';
import { NzCarouselTransformStrategy } from './strategies/transform-strategy';
Expand Down Expand Up @@ -111,7 +118,8 @@ export class NzCarouselComponent implements AfterContentInit, AfterViewInit, OnD
private renderer: Renderer2,
private cdr: ChangeDetectorRef,
private ngZone: NgZone,
private platform: Platform
private platform: Platform,
@Optional() @Inject(NZ_CAROUSEL_CUSTOM_STRATEGIES) private customStrategies: CarouselStrategyRegistryItem[]
) {
this.document = document;
this.renderer.addClass(elementRef.nativeElement, 'ant-carousel');
Expand Down Expand Up @@ -223,6 +231,14 @@ export class NzCarouselComponent implements AfterContentInit, AfterViewInit, OnD
this.strategy.dispose();
}

// Load custom strategies first.
const customStrategy = this.customStrategies ? this.customStrategies.find(s => s.name === this.nzEffect) : null;
if (customStrategy) {
// tslint:disable-next-line:no-any
this.strategy = new (customStrategy.strategy as any)(this, this.cdr, this.renderer);
return;
}

this.strategy =
this.nzEffect === 'scrollx'
? new NzCarouselTransformStrategy(this, this.cdr, this.renderer)
Expand Down
109 changes: 76 additions & 33 deletions components/carousel/nz-carousel.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,44 @@ import { By } from '@angular/platform-browser';
import { dispatchKeyboardEvent } from 'ng-zorro-antd/core';

import { NzCarouselContentDirective } from './nz-carousel-content.directive';
import { NZ_CAROUSEL_CUSTOM_STRATEGIES } from './nz-carousel-definitions';
import { NzCarouselComponent } from './nz-carousel.component';
import { NzCarouselModule } from './nz-carousel.module';
import { NzCarouselOpacityStrategy } from './strategies/opacity-strategy';

@Component({
selector: 'nz-test-carousel-basic',
template: `
<nz-carousel
[nzEffect]="effect"
[nzVertical]="vertical"
[nzDots]="dots"
[nzDotRender]="dotRender"
[nzAutoPlay]="autoPlay"
[nzAutoPlaySpeed]="autoPlaySpeed"
(nzAfterChange)="afterChange($event)"
(nzBeforeChange)="beforeChange($event)"
>
<div nz-carousel-content *ngFor="let index of array">
<h3>{{ index }}</h3>
</div>
<ng-template #dotRender let-index
><a>{{ index + 1 }}</a></ng-template
>
</nz-carousel>
`
})
export class NzTestCarouselBasicComponent {
@ViewChild(NzCarouselComponent) nzCarouselComponent: NzCarouselComponent;
dots = true;
vertical = false;
effect = 'scrollx';
array = [1, 2, 3, 4];
autoPlay = false;
autoPlaySpeed = 3000;
afterChange = jasmine.createSpy('afterChange callback');
beforeChange = jasmine.createSpy('beforeChange callback');
}

describe('carousel', () => {
beforeEach(fakeAsync(() => {
Expand Down Expand Up @@ -296,39 +332,46 @@ describe('carousel', () => {
});
});

@Component({
selector: 'nz-test-carousel-basic',
template: `
<nz-carousel
[nzEffect]="effect"
[nzVertical]="vertical"
[nzDots]="dots"
[nzDotRender]="dotRender"
[nzAutoPlay]="autoPlay"
[nzAutoPlaySpeed]="autoPlaySpeed"
(nzAfterChange)="afterChange($event)"
(nzBeforeChange)="beforeChange($event)"
>
<div nz-carousel-content *ngFor="let index of array">
<h3>{{ index }}</h3>
</div>
<ng-template #dotRender let-index
><a>{{ index + 1 }}</a></ng-template
>
</nz-carousel>
`
})
export class NzTestCarouselBasicComponent {
@ViewChild(NzCarouselComponent) nzCarouselComponent: NzCarouselComponent;
dots = true;
vertical = false;
effect = 'scrollx';
array = [1, 2, 3, 4];
autoPlay = false;
autoPlaySpeed = 3000;
afterChange = jasmine.createSpy('afterChange callback');
beforeChange = jasmine.createSpy('beforeChange callback');
}
describe('carousel custom strategies', () => {
let fixture: ComponentFixture<NzTestCarouselBasicComponent>;
let testComponent: NzTestCarouselBasicComponent;
let carouselWrapper: DebugElement;
let carouselContents: DebugElement[];

beforeEach(fakeAsync(() => {
TestBed.configureTestingModule({
imports: [NzCarouselModule],
declarations: [NzTestCarouselBasicComponent],
providers: [
{
provide: NZ_CAROUSEL_CUSTOM_STRATEGIES,
useValue: [
{
name: 'fade',
strategy: NzCarouselOpacityStrategy
}
]
}
]
});
}));

it('could use custom strategies', fakeAsync(() => {
fixture = TestBed.createComponent(NzTestCarouselBasicComponent);
fixture.detectChanges();
testComponent = fixture.debugElement.componentInstance;
carouselWrapper = fixture.debugElement.query(By.directive(NzCarouselComponent));
carouselContents = fixture.debugElement.queryAll(By.directive(NzCarouselContentDirective));

// The custom provided strategy should also do the work.
testComponent.effect = 'fade';
fixture.detectChanges();
expect(carouselContents[0].nativeElement.classList).toContain('slick-active');
carouselWrapper.nativeElement.querySelector('.slick-dots').lastElementChild.click();
tickMilliseconds(fixture, 700);
expect(carouselWrapper.nativeElement.querySelector('.slick-track').style.transform).toBe('');
}));
});

function tickMilliseconds<T>(fixture: ComponentFixture<T>, seconds: number = 1): void {
fixture.detectChanges();
Expand Down
1 change: 1 addition & 0 deletions components/carousel/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './nz-carousel.module';
export * from './nz-carousel.component';
export * from './nz-carousel-content.directive';
export * from './nz-carousel-definitions';
export * from './strategies/base-strategy';
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": ["../../node_modules/@types/!(node)"],
"typeRoots": ["node_modules/@types/!(node)"],
"lib": ["es2017", "dom"],
"noUnusedParameters": true,
"noUnusedLocals": true,
Expand Down

0 comments on commit a53a43a

Please sign in to comment.