Skip to content

Commit

Permalink
feat(module:slider): add nzReverse property
Browse files Browse the repository at this point in the history
close NG-ZORRO#4937

fix: fix handle position when reverse changes

fix: remove verbose logic

fix: fix keyboard

test: add test

feat: add reverse vertical test
  • Loading branch information
Wendell Hu committed Apr 26, 2020
1 parent 4bfbbf7 commit 2c7b89d
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 60 deletions.
15 changes: 15 additions & 0 deletions components/slider/demo/reverse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
order: 8
title:
zh-CN: 反向
en-US: Reverse
---

## zh-CN

设置 `nzReverse` 可以将滑动条置反。

## en-US

Using `nzReverse` to render slider reversely.

26 changes: 26 additions & 0 deletions components/slider/demo/reverse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-slider-reverse',
template: `
<div>
<nz-slider [ngModel]="30" [nzReverse]="reverse"></nz-slider>
<nz-slider nzRange [ngModel]="[20, 50]" [nzReverse]="reverse"></nz-slider>
Reversed: <nz-switch nzSize="small" [(ngModel)]="reverse"></nz-switch>
</div>
`,
styles: [
`
h4 {
margin: 0 0 16px;
}
.ant-slider-with-marks {
margin-bottom: 44px;
}
`
]
})
export class NzDemoSliderReverseComponent {
reverse = true;
}
1 change: 1 addition & 0 deletions components/slider/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { NzSliderModule } from 'ng-zorro-antd/slider';
| `[nzTipFormatter]` | Slider will pass its value to `tipFormatter`, and display its value in Tooltip, and hide Tooltip when return value is null. | `(value: number) => string` | - |
| `[ngModel]` | The value of slider. When `range` is `false`, use `number`, otherwise, use `[number, number]` | `number \| number[]` | - |
| `[nzVertical]` | If true, the slider will be vertical. | `boolean` | `false` |
| `[nzReverse]` | Reverse the component | `boolean` | `false` |
| `[nzTooltipVisible]` | When set to `always` tooltips are always displayed. When set to `never` they are never displayed | `'default' \| 'always' \| 'never'` | `default` |
| `[nzTooltipPlacement]` | Set the default placement of Tooltip | `string` | |
| `(nzOnAfterChange)` | Fire when `onmouseup` is fired. | `EventEmitter<number[] \| number>` | - |
Expand Down
1 change: 1 addition & 0 deletions components/slider/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { NzSliderModule } from 'ng-zorro-antd/slider';
| `[nzTipFormatter]` | Slider 会把当前值传给 `nzTipFormatter`,并在 Tooltip 中显示 `nzTipFormatter` 的返回值,若为 null,则隐藏 Tooltip。 | `(value: number) => string` | - |
| `[ngModel]` | 设置当前取值。当 `range``false` 时,使用 `number`,否则用 `[number, number]` | `number \| number[]` | - |
| `[nzVertical]` | 值为 `true` 时,Slider 为垂直方向 | `boolean` | `false` |
| `[nzReverse]` | 反向坐标轴 | `boolean` | `false` |
| `[nzTooltipVisible]` | 值为 `always` 时总是显示,值为 `never` 时在任何情况下都不显示 | `'default' \| 'always' \| 'never'` | `default` |
| `[nzTooltipPlacement]` | 设置 Tooltip 的默认位置。 | `string` | |
| `(nzOnAfterChange)` |`onmouseup` 触发时机一致,把当前值作为参数传入。 | `EventEmitter<number[] \| number>` | - |
Expand Down
26 changes: 20 additions & 6 deletions components/slider/handle.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export class NzSliderHandleComponent implements OnChanges {
@ViewChild(NzTooltipDirective, { static: false }) tooltip: NzTooltipDirective;

@Input() vertical: string;
@Input() reverse: string;
@Input() offset: number;
@Input() value: number;
@Input() tooltipVisible: NzSliderShowTooltip = 'default';
Expand All @@ -67,9 +68,9 @@ export class NzSliderHandleComponent implements OnChanges {
constructor(private sliderService: NzSliderService, private cdr: ChangeDetectorRef) {}

ngOnChanges(changes: SimpleChanges): void {
const { offset, value, active, tooltipVisible } = changes;
const { offset, value, active, tooltipVisible, reverse } = changes;

if (offset) {
if (offset || reverse) {
this.updateStyle();
}

Expand Down Expand Up @@ -133,10 +134,23 @@ export class NzSliderHandleComponent implements OnChanges {
}

private updateStyle(): void {
this.style = {
[this.vertical ? 'bottom' : 'left']: `${this.offset}%`,
transform: this.vertical ? 'translateY(50%)' : 'translateX(-50%)'
};
const vertical = this.vertical;
const reverse = this.reverse;
const offset = this.offset;

const positionStyle = vertical
? {
[reverse ? 'top' : 'bottom']: `${offset}%`,
[reverse ? 'bottom' : 'top']: 'auto',
transform: reverse ? null : `translateY(+50%)`
}
: {
[reverse ? 'right' : 'left']: `${offset}%`,
[reverse ? 'left' : 'right']: 'auto',
transform: `translateX(${reverse ? '+' : '-'}50%)`
};

this.style = positionStyle;
this.cdr.markForCheck();
}
}
22 changes: 17 additions & 5 deletions components/slider/slider.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,13 @@ import { NzExtendedMark, NzMarks, NzSliderHandler, NzSliderShowTooltip, NzSlider
[class.ant-slider-with-marks]="marksArray"
>
<div class="ant-slider-rail"></div>
<nz-slider-track [vertical]="nzVertical" [included]="nzIncluded" [offset]="track.offset" [length]="track.length"></nz-slider-track>
<nz-slider-track
[vertical]="nzVertical"
[included]="nzIncluded"
[offset]="track.offset"
[length]="track.length"
[reverse]="nzReverse"
></nz-slider-track>
<nz-slider-step
*ngIf="marksArray"
[vertical]="nzVertical"
Expand All @@ -85,6 +91,7 @@ import { NzExtendedMark, NzMarks, NzSliderHandler, NzSliderShowTooltip, NzSlider
<nz-slider-handle
*ngFor="let handle of handles"
[vertical]="nzVertical"
[reverse]="nzReverse"
[offset]="handle.offset"
[value]="handle.value"
[active]="handle.active"
Expand Down Expand Up @@ -123,6 +130,7 @@ export class NzSliderComponent implements ControlValueAccessor, OnInit, OnChange
@Input() @InputBoolean() nzIncluded: boolean = true;
@Input() @InputBoolean() nzRange: boolean = false;
@Input() @InputBoolean() nzVertical: boolean = false;
@Input() @InputBoolean() nzReverse: boolean = false;
@Input() nzDefaultValue?: NzSliderValue;
@Input() nzMarks: NzMarks | null = null;
@Input() @InputNumber() nzMax = 100;
Expand Down Expand Up @@ -214,7 +222,7 @@ export class NzSliderComponent implements ControlValueAccessor, OnInit, OnChange

e.preventDefault();

const step = isDecrease ? -this.nzStep : this.nzStep;
const step = (isDecrease ? -this.nzStep : this.nzStep) * (this.nzReverse ? -1 : 1);
const newVal = this.nzRange ? (this.value as number[])[this.activeValueIndex!] + step : (this.value as number) + step;
this.setActiveValue(ensureNumberInRange(newVal, this.nzMin, this.nzMax));
}
Expand Down Expand Up @@ -308,16 +316,20 @@ export class NzSliderComponent implements ControlValueAccessor, OnInit, OnChange
private onDragStart(value: number): void {
this.toggleDragMoving(true);
this.cacheSliderProperty();
this.setActiveValueIndex(value);
this.setActiveValue(value);
this.setActiveValueIndex(this.getLogicalValue(value));
this.setActiveValue(this.getLogicalValue(value));
this.showHandleTooltip(this.nzRange ? this.activeValueIndex : 0);
}

private onDragMove(value: number): void {
this.setActiveValue(value);
this.setActiveValue(this.getLogicalValue(value));
this.cdr.markForCheck();
}

private getLogicalValue(value: number): number {
return this.nzReverse ? this.nzMax - value : value;
}

private onDragEnd(): void {
this.nzOnAfterChange.emit(this.getValue(true));
this.toggleDragMoving(false);
Expand Down
94 changes: 64 additions & 30 deletions components/slider/slider.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { LEFT_ARROW, RIGHT_ARROW } from '@angular/cdk/keycodes';
import { DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, UP_ARROW } from '@angular/cdk/keycodes';
import { OverlayContainer } from '@angular/cdk/overlay';
import { Component, DebugElement, OnInit } from '@angular/core';
import { ComponentFixture, fakeAsync, inject, tick } from '@angular/core/testing';
import { AbstractControl, FormBuilder, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { NzSafeAny } from 'ng-zorro-antd';

import { dispatchKeyboardEvent, dispatchMouseEvent } from 'ng-zorro-antd/core/testing';
import { ComponentBed, createComponentBed } from 'ng-zorro-antd/core/testing/componet-bed';
Expand All @@ -19,8 +20,7 @@ describe('nz-slider', () => {
let sliderInstance: NzSliderComponent;
let overlayContainerElement: HTMLElement;

// tslint:disable-next-line:no-any
function getReferenceFromFixture(fixture: ComponentFixture<any>): void {
function getReferenceFromFixture(fixture: ComponentFixture<NzSafeAny>): void {
sliderDebugElement = fixture.debugElement.query(By.directive(NzSliderComponent));
sliderInstance = sliderDebugElement.componentInstance;
sliderNativeElement = sliderInstance.slider.nativeElement;
Expand Down Expand Up @@ -491,6 +491,49 @@ describe('nz-slider', () => {
});
});

describe('reverse', () => {
let testBed: ComponentBed<ReverseSliderComponent>;
let fixture: ComponentFixture<ReverseSliderComponent>;
let sliderDebugElements: DebugElement[];

beforeEach(() => {
testBed = createComponentBed(ReverseSliderComponent, {
imports: [NzSliderModule, FormsModule, ReactiveFormsModule, NoopAnimationsModule]
});
fixture = testBed.fixture;
fixture.detectChanges();

sliderDebugElements = fixture.debugElement.queryAll(By.directive(NzSliderComponent));
});

it('should reverse work', () => {
const trackElement = (sliderDebugElements[0].nativeElement as HTMLElement).querySelector('.ant-slider-track') as HTMLElement;
expect(trackElement.style.right).toBe('0%');

const rangeTrackElement = (sliderDebugElements[1].nativeElement as HTMLElement).querySelector('.ant-slider-track') as HTMLElement;
expect(trackElement.style.right).toBe('0%');
expect(rangeTrackElement.style.width).toBe('100%');

const verticalTrackElement = (sliderDebugElements[2].nativeElement as HTMLElement).querySelector('.ant-slider-track') as HTMLElement;
expect(verticalTrackElement.style.top).toBe('0%');
});

it('should respond to keyboard event reversely', () => {
getReferenceFromFixture(fixture);

dispatchKeyboardEvent(sliderNativeElement, 'keydown', LEFT_ARROW);
dispatchKeyboardEvent(sliderNativeElement, 'keydown', RIGHT_ARROW);
dispatchKeyboardEvent(sliderNativeElement, 'keydown', DOWN_ARROW);
dispatchKeyboardEvent(sliderNativeElement, 'keydown', UP_ARROW);
dispatchKeyboardEvent(sliderNativeElement, 'keydown', LEFT_ARROW);

fixture.detectChanges();

const trackElement = (sliderDebugElements[0].nativeElement as HTMLElement).querySelector('.ant-slider-track') as HTMLElement;
expect(trackElement.style.width).toBe('1%');
});
});

describe('mixed usage', () => {
let testBed: ComponentBed<MixedSliderComponent>;
let fixture: ComponentFixture<MixedSliderComponent>;
Expand Down Expand Up @@ -743,18 +786,14 @@ const styles = `
`;

@Component({
template: `
<nz-slider [nzDisabled]="disabled"></nz-slider>
`,
template: ` <nz-slider [nzDisabled]="disabled"></nz-slider> `,
styles: [styles]
})
class NzTestSliderComponent {
disabled = false;
}
@Component({
template: `
<nz-slider [nzMin]="min" [nzMax]="max"></nz-slider>
`,
template: ` <nz-slider [nzMin]="min" [nzMax]="max"></nz-slider> `,
styles: [styles]
})
class SliderWithMinAndMaxComponent {
Expand All @@ -763,47 +802,46 @@ class SliderWithMinAndMaxComponent {
}

@Component({
template: `
<nz-slider [ngModel]="26"></nz-slider>
`,
template: ` <nz-slider [ngModel]="26"></nz-slider> `,
styles: [styles]
})
class SliderWithValueComponent {}

@Component({
template: `
<nz-slider [nzStep]="step"></nz-slider>
`,
template: ` <nz-slider [nzStep]="step"></nz-slider> `,
styles: [styles]
})
class SliderWithStepComponent {
step = 25;
}

@Component({
template: `
<nz-slider [ngModel]="3" [nzMin]="4" [nzMax]="6"></nz-slider>
`,
template: ` <nz-slider [ngModel]="3" [nzMin]="4" [nzMax]="6"></nz-slider> `,
styles: [styles]
})
class SliderWithValueSmallerThanMinComponent {}

@Component({
template: `
<nz-slider [ngModel]="7" [nzMin]="4" [nzMax]="6"></nz-slider>
`,
template: ` <nz-slider [ngModel]="7" [nzMin]="4" [nzMax]="6"></nz-slider> `,
styles: [styles]
})
class SliderWithValueGreaterThanMaxComponent {}

@Component({
template: `
<nz-slider nzVertical></nz-slider>
`,
template: ` <nz-slider nzVertical></nz-slider> `,
styles: [styles]
})
class VerticalSliderComponent {}

@Component({
template: `
<nz-slider nzReverse></nz-slider>
<nz-slider nzReverse nzRange></nz-slider>
<nz-slider nzVertical nzReverse></nz-slider>
`
})
class ReverseSliderComponent {}

@Component({
template: `
<nz-slider
Expand Down Expand Up @@ -850,19 +888,15 @@ class SliderWithFormControlComponent implements OnInit {
}

@Component({
template: `
<nz-slider [nzTooltipVisible]="show" [ngModel]="value"></nz-slider>
`
template: ` <nz-slider [nzTooltipVisible]="show" [ngModel]="value"></nz-slider> `
})
class SliderShowTooltipComponent {
show: NzSliderShowTooltip = 'default';
value = 0;
}

@Component({
template: `
<nz-slider [nzRange]="range"></nz-slider>
`
template: ` <nz-slider [nzRange]="range"></nz-slider> `
})
class NzTestSliderKeyboardComponent {
range = false;
Expand Down
Loading

0 comments on commit 2c7b89d

Please sign in to comment.