Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(module:carousel): support custom strategies #3501

Merged
merged 5 commits into from
Jun 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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