Skip to content

Commit

Permalink
feat(module:date-picker): support date-picker placement (#7527)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBeard30 committed Jul 11, 2022
1 parent d8b26dd commit a652470
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 31 deletions.
34 changes: 34 additions & 0 deletions components/core/overlay/overlay-position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,37 @@ export function getPlacementName(position: ConnectedOverlayPositionChange): stri
}
return undefined;
}

export const DATE_PICKER_POSITION_MAP = {
bottomLeft: new ConnectionPositionPair(
{ originX: 'start', originY: 'bottom' },
{ overlayX: 'start', overlayY: 'top' },
undefined,
2
),
topLeft: new ConnectionPositionPair(
{ originX: 'start', originY: 'top' },
{ overlayX: 'start', overlayY: 'bottom' },
undefined,
-2
),
bottomRight: new ConnectionPositionPair(
{ originX: 'end', originY: 'bottom' },
{ overlayX: 'end', overlayY: 'top' },
undefined,
2
),
topRight: new ConnectionPositionPair(
{ originX: 'end', originY: 'top' },
{ overlayX: 'end', overlayY: 'bottom' },
undefined,
-2
)
};

export const DEFAULT_DATE_PICKER_POSITIONS = [
DATE_PICKER_POSITION_MAP.bottomLeft,
DATE_PICKER_POSITION_MAP.topLeft,
DATE_PICKER_POSITION_MAP.bottomRight,
DATE_PICKER_POSITION_MAP.topRight
];
48 changes: 48 additions & 0 deletions components/date-picker/date-picker.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,52 @@ describe('NzDatePickerComponent', () => {
openPickerByClickTrigger();
expect(overlayContainerElement.children[0].classList).toContain('cdk-overlay-backdrop');
}));
it('should support nzPlacement', fakeAsync(() => {
fixtureInstance.nzPlacement = 'bottomLeft';
fixture.detectChanges();
openPickerByClickTrigger();
let element = queryFromOverlay('.ant-picker-dropdown');
expect(element.classList.contains('ant-picker-dropdown-placement-bottomLeft')).toBe(true);
expect(element.classList.contains('ant-picker-dropdown-placement-topLeft')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-bottomRight')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-topRight')).toBe(false);
triggerInputBlur();
fixture.detectChanges();
tick(500);
fixture.detectChanges();
fixtureInstance.nzPlacement = 'topLeft';
fixture.detectChanges();
openPickerByClickTrigger();
element = queryFromOverlay('.ant-picker-dropdown');
expect(element.classList.contains('ant-picker-dropdown-placement-bottomLeft')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-topLeft')).toBe(true);
expect(element.classList.contains('ant-picker-dropdown-placement-bottomRight')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-topRight')).toBe(false);
triggerInputBlur();
fixture.detectChanges();
tick(500);
fixture.detectChanges();
fixtureInstance.nzPlacement = 'bottomRight';
fixture.detectChanges();
openPickerByClickTrigger();
element = queryFromOverlay('.ant-picker-dropdown');
expect(element.classList.contains('ant-picker-dropdown-placement-bottomLeft')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-topLeft')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-bottomRight')).toBe(true);
expect(element.classList.contains('ant-picker-dropdown-placement-topRight')).toBe(false);
triggerInputBlur();
fixture.detectChanges();
tick(500);
fixture.detectChanges();
fixtureInstance.nzPlacement = 'topRight';
fixture.detectChanges();
openPickerByClickTrigger();
element = queryFromOverlay('.ant-picker-dropdown');
expect(element.classList.contains('ant-picker-dropdown-placement-bottomLeft')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-topLeft')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-bottomRight')).toBe(false);
expect(element.classList.contains('ant-picker-dropdown-placement-topRight')).toBe(true);
}));
});

describe('panel switch and move forward/afterward', () => {
Expand Down Expand Up @@ -1289,6 +1335,7 @@ describe('in form', () => {
[nzBorderless]="nzBorderless"
[nzInline]="nzInline"
[nzBackdrop]="nzBackdrop"
[nzPlacement]="nzPlacement"
></nz-date-picker>
<ng-template #tplDateRender let-current>
<div [class.test-first-day]="current.getDate() === 1">{{ current.getDate() }}</div>
Expand Down Expand Up @@ -1348,6 +1395,7 @@ class NzTestDatePickerComponent {
nzBorderless = false;
nzInline = false;
nzBackdrop = false;
nzPlacement = 'bottomLeft';

// nzRanges;
nzOnPanelChange(_: string): void {}
Expand Down
47 changes: 16 additions & 31 deletions components/date-picker/date-picker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { slideMotion } from 'ng-zorro-antd/core/animation';
import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/config';
import { NzFormNoStatusService, NzFormStatusService } from 'ng-zorro-antd/core/form';
import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation';
import { DEFAULT_DATE_PICKER_POSITIONS, DATE_PICKER_POSITION_MAP } from 'ng-zorro-antd/core/overlay';
import { CandyDate, cloneDate, CompatibleValue, wrongSortOrder } from 'ng-zorro-antd/core/time';
import {
BooleanInput,
Expand Down Expand Up @@ -83,6 +84,7 @@ const POPUP_STYLE_PATCH = { position: 'relative' }; // Aim to override antd's st
const NZ_CONFIG_MODULE_NAME: NzConfigKey = 'datePicker';

export type NzDatePickerSizeType = 'large' | 'default' | 'small';
export type NzPlacement = 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight';

/**
* The base picker for all common APIs
Expand Down Expand Up @@ -303,6 +305,7 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
@Input() @WithConfig() nzSuffixIcon: string | TemplateRef<NzSafeAny> = 'calendar';
@Input() @WithConfig() nzBackdrop = false;
@Input() nzId: string | null = null;
@Input() nzPlacement: NzPlacement = 'bottomLeft';

// TODO(@wenqi73) The PanelMode need named for each pickers and export
@Output() readonly nzOnPanelChange = new EventEmitter<NzDateMode | NzDateMode[] | string | string[]>();
Expand Down Expand Up @@ -335,36 +338,7 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
inputValue!: NzSafeAny;
activeBarStyle: object = {};
overlayOpen: boolean = false; // Available when "nzOpen" = undefined
overlayPositions: ConnectionPositionPair[] = [
{
offsetY: 2,
originX: 'start',
originY: 'bottom',
overlayX: 'start',
overlayY: 'top'
},
{
offsetY: -2,
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'bottom'
},
{
offsetY: 2,
originX: 'end',
originY: 'bottom',
overlayX: 'end',
overlayY: 'top'
},
{
offsetY: -2,
originX: 'end',
originY: 'top',
overlayX: 'end',
overlayY: 'bottom'
}
] as ConnectionPositionPair[];
overlayPositions: ConnectionPositionPair[] = [...DEFAULT_DATE_PICKER_POSITIONS];
currentPositionX: HorizontalConnectionPos = 'start';
currentPositionY: VerticalConnectionPos = 'bottom';

Expand Down Expand Up @@ -680,7 +654,7 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
}

ngOnChanges(changes: SimpleChanges): void {
const { nzStatus } = changes;
const { nzStatus, nzPlacement } = changes;
if (changes.nzPopupStyle) {
// Always assign the popup style patch
this.nzPopupStyle = this.nzPopupStyle ? { ...this.nzPopupStyle, ...POPUP_STYLE_PATCH } : POPUP_STYLE_PATCH;
Expand Down Expand Up @@ -712,6 +686,10 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
if (nzStatus) {
this.setStatusStyles(this.nzStatus, this.hasFeedback);
}

if (nzPlacement) {
this.setPlacement(this.nzPlacement);
}
}

ngOnDestroy(): void {
Expand Down Expand Up @@ -877,4 +855,11 @@ export class NzDatePickerComponent implements OnInit, OnChanges, OnDestroy, Afte
}
});
}

private setPlacement(placement: NzPlacement): void {
const position: ConnectionPositionPair = DATE_PICKER_POSITION_MAP[placement];
this.overlayPositions = [position, ...DEFAULT_DATE_PICKER_POSITIONS];
this.currentPositionX = position.originX;
this.currentPositionY = position.originY;
}
}
14 changes: 14 additions & 0 deletions components/date-picker/demo/placement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
order: 6
title:
zh-CN: 自定义位置
en-US: Placement
---

## zh-CN

可以通过 `nzPlacement` 手动指定弹出的位置。

## en-US

You can manually specify the position of the popup via `nzPlacement`.
29 changes: 29 additions & 0 deletions components/date-picker/demo/placement.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-date-picker-placement',
template: `
<nz-radio-group [(ngModel)]="placement">
<label nz-radio-button nzValue="bottomLeft">bottomLeft</label>
<label nz-radio-button nzValue="bottomRight">bottomRight</label>
<label nz-radio-button nzValue="topLeft">topLeft</label>
<label nz-radio-button nzValue="topRight">topRight</label>
</nz-radio-group>
<br />
<br />
<nz-date-picker [nzPlacement]="placement"></nz-date-picker>
<br />
<nz-range-picker [nzPlacement]="placement"></nz-range-picker>
`,
styles: [
`
nz-date-picker,
nz-range-picker {
margin: 0 8px 12px 0;
}
`
]
})
export class NzDemoDatePickerPlacementComponent {
placement: 'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight' = 'bottomLeft';
}
1 change: 1 addition & 0 deletions components/date-picker/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ The following APIs are shared by nz-date-picker, nz-range-picker.
| `[nzRenderExtraFooter]` | render extra footer in panel | `TemplateRef \| string \| (() => TemplateRef \| string)` | - |
| `[nzSize]` | determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | `'large' \| 'small'` | - | - |
| `[nzStatus]` | Set validation status | `'error' \| 'warning'` | - |
| `[nzPlacement]` | The position where the selection box pops up | `'bottomLeft' \| 'bottomRight' \| 'topLeft' \| 'topRight'` | `'bottomLeft'` | |
| `[nzSuffixIcon]` | the custom suffix icon | `string` \| `TemplateRef` | - ||
| `[nzBorderless]` | remove the border | `boolean` | `false` | - |
| `[nzInline]` | inline mode | `boolean` | `false` | - |
Expand Down
1 change: 1 addition & 0 deletions components/date-picker/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ registerLocaleData(zh);
| `[nzRenderExtraFooter]` | 在面板中添加额外的页脚 | `TemplateRef \| string \| (() => TemplateRef \| string)` | - |
| `[nzSize]` | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | `'large' \| 'small'` | - | - |
| `[nzStatus]` | 设置校验状态 | `'error' \| 'warning'` | - |
| `[nzPlacement]` | 选择框弹出的位置 | `'bottomLeft' \| 'bottomRight' \| 'topLeft' \| 'topRight'` | `'bottomLeft'` | |
| `[nzSuffixIcon]` | 自定义的后缀图标 | `string` \| `TemplateRef` | - ||
| `[nzBorderless]` | 移除边框 | `boolean` | `false` | - |
| `[nzInline]` | 内联模式 | `boolean` | `false` | - |
Expand Down

0 comments on commit a652470

Please sign in to comment.