From a7ee5768f818f9d0b7f30e82f26d1192d41f1d31 Mon Sep 17 00:00:00 2001
From: Hsuan Lee
Date: Sat, 6 Jan 2018 16:40:44 +0800
Subject: [PATCH] feat(module:datepicker): add range-picker component (#656)
* feat(module:datepicker): add range-picker component
feat(module:datepicker): support [nzShowTime]
feat(module:datepicker): hover to highlight the range
feat(module:datepicker): support input
export component
* feat(module:locale): add russian locale for the date range component
---
.../calendar/nz-calendar.component.ts | 254 +++++---
.../datepicker/nz-datepicker.module.ts | 5 +-
.../datepicker/nz-rangepicker.component.ts | 612 ++++++++++++++++++
src/components/datepicker/style/patch.less | 24 +
src/components/locale/locales/en-US.ts | 2 +
src/components/locale/locales/ru-RU.ts | 2 +
src/components/locale/locales/tr-TR.ts | 2 +
src/components/locale/locales/zh-CN.ts | 2 +
src/components/locale/locales/zh-TW.ts | 2 +
src/components/locale/nz-locale.class.ts | 2 +
src/components/ng-zorro-antd.module.ts | 1 +
.../nz-demo-datepicker-basic.component.ts | 10 +-
...-demo-datepicker-disable-date.component.ts | 11 +-
.../nz-demo-datepicker-disabled.component.ts | 8 +-
.../nz-demo-datepicker-formatter.component.ts | 6 +
.../nz-demo-datepicker-size.component.ts | 19 +-
.../nz-demo-datepicker-time.component.ts | 5 +-
.../nz-demo-datepicker.html | 123 +++-
.../nz-demo-locale-all.component.ts | 1 +
19 files changed, 965 insertions(+), 126 deletions(-)
create mode 100644 src/components/datepicker/nz-rangepicker.component.ts
diff --git a/src/components/calendar/nz-calendar.component.ts b/src/components/calendar/nz-calendar.component.ts
index 9923012ff0d..1557759392c 100644
--- a/src/components/calendar/nz-calendar.component.ts
+++ b/src/components/calendar/nz-calendar.component.ts
@@ -35,6 +35,7 @@ export interface DayInterface {
isNextMonth: boolean;
isCurrentDay: boolean;
isSelectedDay: boolean;
+ isInRange?: boolean;
title: string;
date: Moment;
disabled: boolean;
@@ -46,6 +47,8 @@ export interface WeekInterface {
days: DayInterface[];
}
+export enum RangePart { Start = 0, End = 1 }
+
@Component({
selector : 'nz-calendar',
encapsulation: ViewEncapsulation.None,
@@ -99,57 +102,62 @@ export interface WeekInterface {
[class.ant-patch-full-height]="nzDatePicker"
*ngIf="nzMode == 'year'">
-
-
- {{ _min }}
- |
-
+
+
+ {{ _min }}
+ |
+
-
-
-
-
- {{ day.number }}
-
-
-
-
+
+
+
+
+ {{ day.number }}
+
+
+
- |
-
-
-
- {{ day.number }}
- |
-
-
+
+ |
+
+
+
+
+ {{ day.number }}
+
+ |
+
+
-
-
-
-
- {{ month.name }}
-
-
-
-
-
- |
-
-
-
-
- {{ month.name }}
+
+
+
+
+ {{ month.name }}
+
+
+
- |
-
-
+
+ |
+
+
+
+
+ {{ month.name }}
+
+ |
+
+
@@ -206,6 +214,7 @@ export class NzCalendarComponent implements OnInit {
private _datePicker = false;
private _fullScreen = true;
private _showHeader = true;
+ private _isRange = false;
_el: HTMLElement;
_weeksCalendar: WeekInterface[] = [];
@@ -213,17 +222,21 @@ export class NzCalendarComponent implements OnInit {
_listOfWeekName: string[] = [];
_listOfMonthName: string[] = [];
_listOfYearName: number[] = [];
+ _disabledDate: (value: Date) => boolean;
_yearUnit = '年';
_monthUnit = '月';
_showMonth = moment(new Date()).month();
_showYear = moment(new Date()).year();
_value: Date = new Date();
+ _rangeValue: Date[] = [null, null];
+ _hoveringSelectValue: Date;
_locale = this._localeService.getLocale().locale;
@ContentChild('dateCell') dateCell: TemplateRef;
@ContentChild('monthCell') monthCell: TemplateRef;
@Output() nzClickDay: EventEmitter = new EventEmitter();
@Output() nzClickMonth: EventEmitter = new EventEmitter();
+ @Output() nzHoverDay: EventEmitter = new EventEmitter();
@Input() nzClearTime = true;
@Input() nzMode = 'year';
@@ -245,7 +258,24 @@ export class NzCalendarComponent implements OnInit {
return this._showHeader;
}
- @Input() nzDisabledDate: (date: Date) => boolean = () => false;
+ @Input()
+ set nzIsRange(value: boolean) {
+ this._isRange = toBoolean(value);
+ }
+
+ get nzIsRange(): boolean {
+ return this._isRange;
+ }
+
+ @Input()
+ set nzDisabledDate(value: (value: Date) => boolean) {
+ this._disabledDate = value;
+ this._buildCalendar();
+ }
+
+ get nzDisabledDate(): (value: Date) => boolean {
+ return this._disabledDate;
+ }
@Input()
@HostBinding('class.ant-patch-full-height')
@@ -272,6 +302,29 @@ export class NzCalendarComponent implements OnInit {
return this._value || new Date();
}
+ @Input()
+ get nzRangeValue(): Date[] {
+ return this._rangeValue;
+ }
+
+ set nzRangeValue(value: Date[]) {
+ this._rangeValue = value;
+ this._buildCalendar();
+ }
+
+ @Input()
+ get nzHoveringSelectValue(): Date {
+ return this._hoveringSelectValue;
+ }
+
+ set nzHoveringSelectValue(value: Date) {
+ if (this._hoveringSelectValue === value) {
+ return;
+ }
+ this._hoveringSelectValue = value;
+ this._buildCalendar();
+ }
+
@Input()
set nzShowYear(value: number) {
this._showYear = value;
@@ -328,6 +381,44 @@ export class NzCalendarComponent implements OnInit {
this.nzClickMonth.emit(month);
}
+ _onDayHover($event: MouseEvent, day: DayInterface): void {
+ $event.preventDefault();
+ $event.stopPropagation();
+ if (day.disabled || day.date.isSame(this._hoveringSelectValue)) {
+ return;
+ }
+ this.nzHoverDay.emit(day);
+ }
+
+ _isSelectedDay(date: Moment, month: Moment): boolean {
+ if (this.nzIsRange) {
+ return (date.isSame(this._rangeValue[RangePart.Start], 'day')
+ || date.isSame(this._rangeValue[RangePart.End], 'day')
+ || date.isSame(this._hoveringSelectValue, 'day'))
+ && date.month() === month.month();
+ } else {
+ return date.isSame(this.nzValue, 'day');
+ }
+ }
+
+ _isInRange(date: Moment, month: Moment): boolean {
+ let ghostDate: Date;
+ if (this.nzIsRange && date.month() === month.month()) {
+ if (this._rangeValue.every(e => moment(e).isValid())) {
+ return date.isBetween.apply(date, this._rangeValue);
+ }
+ ghostDate = this._rangeValue.find(e => moment(e).isValid());
+ if (ghostDate && this._hoveringSelectValue) {
+ const start = moment.min(moment(ghostDate), moment(this._hoveringSelectValue)).toDate();
+ const end = moment.max(moment(ghostDate), moment(this._hoveringSelectValue)).toDate();
+ return date.isBetween(start, end);
+ }
+ return false;
+ } else {
+ return false;
+ }
+ }
+
_buildMonth(d: Moment): WeekInterface[] {
const weeks: WeekInterface[] = [];
const _rawDate = this._removeTime(d);
@@ -355,7 +446,8 @@ export class NzCalendarComponent implements OnInit {
isLastMonth : date.month() < month.month(),
isNextMonth : date.month() > month.month(),
isCurrentDay : date.isSame(new Date(), 'day'),
- isSelectedDay: date.isSame(this.nzValue, 'day'),
+ isSelectedDay: this._isSelectedDay(date, month),
+ isInRange : this._isInRange(date, month),
title : date.format('YYYY-MM-DD'),
date,
disabled : this.nzDisabledDate && this.nzDisabledDate(date.toDate()),
diff --git a/src/components/datepicker/nz-datepicker.module.ts b/src/components/datepicker/nz-datepicker.module.ts
index b6d8bbc39d1..bfee51fb829 100644
--- a/src/components/datepicker/nz-datepicker.module.ts
+++ b/src/components/datepicker/nz-datepicker.module.ts
@@ -8,11 +8,12 @@ import { NzLocaleModule } from '../locale/index';
import { NzTimePickerModule } from '../time-picker/nz-timepicker.module';
import { NzUtilModule } from '../util/nz-util.module';
import { NzDatePickerComponent } from './nz-datepicker.component';
+import { NzRangePickerComponent } from './nz-rangepicker.component';
@NgModule({
imports : [ CommonModule, NzTimePickerModule, NzUtilModule, NzInputModule, NzCalendarModule, FormsModule, OverlayModule, NzLocaleModule ],
- declarations: [ NzDatePickerComponent ],
- exports : [ NzDatePickerComponent ]
+ declarations: [ NzDatePickerComponent, NzRangePickerComponent ],
+ exports : [ NzDatePickerComponent, NzRangePickerComponent ]
})
export class NzDatePickerModule {
}
diff --git a/src/components/datepicker/nz-rangepicker.component.ts b/src/components/datepicker/nz-rangepicker.component.ts
new file mode 100644
index 00000000000..904f40c3656
--- /dev/null
+++ b/src/components/datepicker/nz-rangepicker.component.ts
@@ -0,0 +1,612 @@
+import { ConnectedOverlayPositionChange, ConnectionPositionPair } from '@angular/cdk/overlay';
+import {
+ forwardRef,
+ ChangeDetectorRef,
+ Component,
+ ElementRef,
+ Input,
+ OnInit,
+ QueryList,
+ ViewChild,
+ ViewChildren,
+ ViewEncapsulation
+} from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import * as moment from 'moment';
+import { DayInterface, MonthInterface, RangePart } from '../calendar/nz-calendar.component';
+import { dropDownAnimation } from '../core/animation/dropdown-animations';
+import { DEFAULT_DATEPICKER_POSITIONS } from '../core/overlay/overlay-position-map';
+import { NzLocaleService } from '../locale/index';
+import { NzTimePickerInnerComponent } from '../time-picker/nz-timepicker-inner.component';
+import { toBoolean } from '../util/convert';
+
+@Component({
+ selector: 'nz-rangepicker',
+ encapsulation: ViewEncapsulation.None,
+ animations: [
+ dropDownAnimation
+ ],
+ template: `
+
+
+
+ ~
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => NzRangePickerComponent),
+ multi: true
+ }
+ ],
+ styleUrls: [
+ './style/index.less',
+ './style/patch.less'
+ ]
+})
+export class NzRangePickerComponent implements ControlValueAccessor, OnInit {
+ private _disabled = false;
+ private _showTime: Partial = null;
+ private _now = moment();
+ private _el;
+ private _oldValue: Date[] = this._defaultRangeValue;
+ private _value: Date[] = this._defaultRangeValue;
+
+ // avoid reference types
+ private get _defaultRangeValue(): Date[] {
+ return [null, null];
+ }
+
+ private get start(): moment.Moment {
+ return moment(this._value[RangePart.Start]);
+ }
+
+ private get end(): moment.Moment {
+ return moment(this._value[RangePart.End]);
+ }
+
+ _part = RangePart; // provided to template
+ hoveringSelectValue: Date;
+ _open;
+ _disabledDate: (value: Date) => boolean;
+ _disabledDatePart: Array<(value: Date) => boolean> = [null, null];
+ _mode = ['year', 'year'];
+ _selectedMonth: number[] = [];
+ _selectedYear: number[] = [];
+ _selectedDate: number[] = [];
+ _showMonth = [this._now.month(), this._now.clone().add(1, 'month').month()];
+ _showYear = [this._now.year(), this._now.year()];
+ _yearPanel: string[][] = [];
+ _startDecade = new Array(2).fill(Math.floor(this._showYear[RangePart.Start] / 10) * 10);
+ _triggerWidth = 0;
+ _dropDownPosition = 'bottom';
+ _positions: ConnectionPositionPair[] = [...DEFAULT_DATEPICKER_POSITIONS];
+ @ViewChild('trigger') trigger;
+ onTouched: () => void = () => null;
+ onChange: (value: Date[]) => void = () => null;
+ @Input() nzSize = '';
+ @Input() nzFormat = 'YYYY-MM-DD';
+ @Input() nzAllowClear = true;
+ @Input() nzPlaceholder: string[] = [this._locale.translate('DateTime.chooseStartDatePlease'), this._locale.translate('DateTime.chooseEndDatePlease')];
+ @ViewChildren(NzTimePickerInnerComponent) timePickerInner: QueryList;
+
+ get showClearIcon(): boolean {
+ return this._isComplete() && !this.nzDisabled && this.nzAllowClear;
+ }
+
+ @Input()
+ set nzShowTime(value: Partial) {
+ if (typeof value === 'string' || typeof value === 'boolean') {
+ this._showTime = toBoolean(value) ? {} : null;
+ } else {
+ this._showTime = value;
+ }
+ }
+
+ get nzShowTime(): Partial {
+ return this._showTime;
+ }
+
+ @Input()
+ set nzDisabled(value: boolean) {
+ this._disabled = toBoolean(value);
+ this._closeCalendar();
+ }
+
+ get nzDisabled(): boolean {
+ return this._disabled;
+ }
+
+ get nzValue(): Date[] {
+ return this._value || this._defaultRangeValue;
+ }
+
+ set nzValue(value: Date[]) {
+ this._updateValue(value);
+ }
+
+ @Input()
+ set nzDisabledDate(value: (value: Date) => boolean) {
+ this._disabledDate = value;
+ this._bindDisabledDateToPart();
+ }
+
+ get nzDisabledDate(): (value: Date) => boolean {
+ return this._disabledDate;
+ }
+
+ constructor(private _elementRef: ElementRef, private _cdr: ChangeDetectorRef, private _locale: NzLocaleService) {
+ this._el = this._elementRef.nativeElement;
+ }
+
+ ngOnInit(): void {
+ this._generateYearPanel();
+ }
+
+ _bindDisabledDateToPart(): void {
+ // when the mode is month, not needed disable it
+ this._disabledDatePart[RangePart.Start] = this._mode[RangePart.Start] === 'month' ? null : this._disabledDate;
+ this._disabledDatePart[RangePart.End] = this._mode[RangePart.End] === 'month' ? null : this._disabledDate;
+ }
+
+ _generateYearPanel(): void {
+ let _t = [];
+ for (let i = 0; i < 10; i++) {
+ if (i === 1 || i === 4 || i === 7 || i === 9) {
+ _t.push(i);
+ this._yearPanel.push(_t);
+ _t = [];
+ } else {
+ _t.push(i);
+ }
+ }
+ this._yearPanel[0].unshift('start');
+ this._yearPanel[3].push('end');
+ }
+
+ _openCalendar(): void {
+ if (this.nzDisabled) {
+ return;
+ }
+ this._mode = ['year', 'year'];
+ this._open = true;
+ this._setTriggerWidth();
+ this._initShow();
+ }
+
+ _closeCalendar(): void {
+ if (!this._open) {
+ return;
+ }
+ if (this._isComplete()) {
+ this._onChange();
+ } else {
+ this._value = [...this._oldValue];
+ }
+ this._open = false;
+ }
+
+ _clearValue(e: MouseEvent): void {
+ e.preventDefault();
+ e.stopPropagation();
+ this.nzValue = this._defaultRangeValue;
+ this.onChange(this._value);
+ }
+
+ _setTriggerWidth(): void {
+ this._triggerWidth = this.trigger.nativeElement.getBoundingClientRect().width;
+ }
+
+ _setShowYear(year: number, part: RangePart, $event: MouseEvent): void {
+ $event.stopPropagation();
+ this._showYear[part] = year;
+ this._mode[part] = 'month';
+ }
+
+ _isValid(part: RangePart): boolean {
+ return moment(this._value[part]).isValid();
+ }
+
+ _isComplete(): boolean {
+ return this.start.isValid() && this.end.isValid();
+ }
+
+ _changeTime($event: Date, part: RangePart): void {
+ this._value[part] = $event;
+ }
+
+ _blurInput(box: HTMLInputElement, part: RangePart): void {
+ if (Date.parse(box.value)) {
+ this._value[part] = new Date(box.value);
+ this._onChange();
+ }
+ }
+
+ _hoverDay(day: DayInterface): void {
+ if (!this._isComplete() && this._value.some(e => moment(e).isValid())) {
+ this.hoveringSelectValue = day.date.toDate();
+ } else {
+ this.hoveringSelectValue = null;
+ }
+ }
+
+ _clickDay(day: DayInterface, part: RangePart): void {
+ const newDate = day.date.toDate();
+ // if have completed, then reset
+ if (this._isComplete()) {
+ this._value = this._defaultRangeValue;
+ this._value[part] = newDate;
+ this.rangeValueSort();
+ return;
+ }
+ if (moment(this._value[part]).isValid()) {
+ if (part === RangePart.Start) {
+ this._value[RangePart.End] = newDate;
+ } else {
+ this._value[RangePart.Start] = newDate;
+ }
+ } else {
+ this._value[part] = newDate;
+ }
+ // the result depends the before step
+ if (this._isComplete()) {
+ this.rangeValueSort();
+ if (!this.nzShowTime) {
+ this._closeCalendar();
+ return;
+ }
+ this._initShow();
+ }
+ this.rangeValueSort();
+ }
+
+ _clickMonth(month: MonthInterface, part: RangePart): void {
+ this._showMonth[part] = month.index;
+ this._mode[part] = 'year';
+ this._bindDisabledDateToPart();
+ this.adjustShowMonth();
+ }
+
+ _changeTimeView($event: MouseEvent): void {
+ $event.stopPropagation();
+ this._mode = ['time', 'time'];
+ this.setSelectedValue();
+ setTimeout(_ => {
+ this.timePickerInner.forEach(e => e._initPosition());
+ });
+ }
+
+ _changeYearView($event: MouseEvent): void {
+ $event.stopPropagation();
+ this._mode = ['year', 'year'];
+ }
+
+ _showBtn(part: RangePart): boolean {
+ if (this._mode[part] === 'month') {
+ return true;
+ }
+ const showStart = moment().month(this._showMonth[RangePart.Start]).year(this._showYear[RangePart.Start]);
+ const showEnd = moment().month(this._showMonth[RangePart.End]).year(this._showYear[RangePart.End]);
+ return !showStart.add(1, 'month').isSame(showEnd, 'month');
+ }
+
+ _preYear(part: RangePart): void {
+ this._showYear[part] = this._showYear[part] - 1;
+ this.adjustShowMonth();
+ }
+
+ _nextYear(part: RangePart): void {
+ this._showYear[part] = this._showYear[part] + 1;
+ this.adjustShowMonth();
+ }
+
+ _preMonth(part: RangePart): void {
+ if (this._showMonth[part] - 1 < 0) {
+ this._showMonth[part] = 11;
+ this._preYear(part);
+ } else {
+ this._showMonth[part] = this._showMonth[part] - 1;
+ }
+ }
+
+ _nextMonth(part: RangePart): void {
+ if (this._showMonth[part] + 1 > 11) {
+ this._showMonth[part] = 0;
+ this._nextYear(part);
+ } else {
+ this._showMonth[part] = this._showMonth[part] + 1;
+ }
+ }
+
+ _preDecade(part: RangePart): void {
+ this._startDecade[part] = this._startDecade[part] - 10;
+ }
+
+ _nextDecade(part: RangePart): void {
+ this._startDecade[part] = this._startDecade[part] + 10;
+ }
+
+ rangeValueSort(): void {
+ if (this.start.isValid() && this.end.isValid() && this.start.isAfter(this.end)) {
+ this._value = this._value.reverse();
+ } else {
+ this._value = this._value.concat();
+ }
+ }
+
+ _initShow(): void {
+ if (this.start.isValid()) {
+ this._showMonth[RangePart.Start] = this.start.month();
+ this._showYear[RangePart.Start] = this.start.year();
+ } else {
+ this._showMonth[RangePart.Start] = this._now.month();
+ this._showYear[RangePart.Start] = this._now.year();
+ }
+ if (this.end.isValid() && !this.start.isSameOrAfter(this.end, 'month')) {
+ this._showMonth[RangePart.End] = this.end.month();
+ this._showYear[RangePart.End] = this.end.year();
+ } else {
+ const nextMonthOfStart = this.start.clone().add(1, 'month');
+ const nextMonthOfNow = this._now.clone().add(1, 'month');
+ this._showMonth[RangePart.End] = this.start.isValid() ? nextMonthOfStart.month() : nextMonthOfNow.month();
+ this._showYear[RangePart.End] = this.start.isValid() ? nextMonthOfStart.year() : nextMonthOfNow.year();
+ }
+ this._showMonth = this._showMonth.concat();
+ this._showYear = this._showYear.concat();
+ }
+
+ adjustShowMonth(): void {
+ if (this._showYear[RangePart.Start] === this._showYear[RangePart.End] && this._showMonth[RangePart.Start] === this._showMonth[RangePart.End]) {
+ this._nextMonth(RangePart.End);
+ }
+ }
+
+ onPositionChange(position: ConnectedOverlayPositionChange): void {
+ const _position = position.connectionPair.originY === 'bottom' ? 'top' : 'bottom';
+ if (this._dropDownPosition !== _position) {
+ this._dropDownPosition = _position;
+ this._cdr.detectChanges();
+ }
+ }
+
+ setSelectedValue(): void {
+ this._selectedYear = [this.start.year(), this.end.year()];
+ this._selectedMonth = [this.start.month(), this.end.month()];
+ this._selectedDate = [this.start.date(), this.end.date()];
+ }
+
+ isValueChange(): boolean {
+ return this._value.some((value: Date, index: number) => {
+ return this._oldValue[index] === null
+ || (moment.isDate(this._oldValue[index])
+ && moment.isDate(value)
+ && this._oldValue[index].getTime() !== value.getTime());
+ });
+ }
+
+ writeValue(value: Date[]): void {
+ this._updateValue(value);
+ }
+
+ registerOnChange(fn: (_: Date[]) => {}): void {
+ this.onChange = fn;
+ }
+
+ registerOnTouched(fn: () => {}): void {
+ this.onTouched = fn;
+ }
+
+ setDisabledState(isDisabled: boolean): void {
+ this.nzDisabled = isDisabled;
+ }
+
+ private _updateValue(value: Date[]): void {
+ if (Array.isArray(value) && value.length === 2) {
+ this._value = [value[RangePart.Start], value[RangePart.End]];
+ } else {
+ this._value = this._defaultRangeValue;
+ }
+ this._oldValue = [...this._value];
+ }
+
+ private _onChange(): void {
+ if (this._isValid(RangePart.Start) && this._isValid(RangePart.End) && this.isValueChange()) {
+ this.onChange(this._value);
+ this._oldValue = [...this._value];
+ }
+ }
+}
diff --git a/src/components/datepicker/style/patch.less b/src/components/datepicker/style/patch.less
index 73a9ee1484a..fa731742aeb 100644
--- a/src/components/datepicker/style/patch.less
+++ b/src/components/datepicker/style/patch.less
@@ -14,3 +14,27 @@ nz-datepicker {
top: -2px;
}
}
+
+.ant-input > .@{calendar-prefix-cls}-range-picker-input {
+ background-color: transparent;
+ border: 0;
+ height: 99%;
+ outline: 0;
+ width: 43%;
+ text-align: center;
+ vertical-align: top;
+ .placeholder();
+
+ &[disabled] {
+ cursor: not-allowed;
+ }
+
+ &:focus {
+ border: 0;
+ box-shadow: none;
+ }
+}
+
+.@{calendar-prefix-cls}-time-picker-body {
+ height: 247px;
+}
diff --git a/src/components/locale/locales/en-US.ts b/src/components/locale/locales/en-US.ts
index 04cff08cafd..2edb6f361b0 100644
--- a/src/components/locale/locales/en-US.ts
+++ b/src/components/locale/locales/en-US.ts
@@ -34,6 +34,8 @@ export const enUS: NzLocale = {
chooseDate: 'Select date',
chooseTimePlease: 'Select time',
chooseDatePlease: 'Select date',
+ chooseStartDatePlease: 'Start date',
+ chooseEndDatePlease: 'End date',
thisMoment: 'This moment',
today: 'Today',
ok: 'Ok',
diff --git a/src/components/locale/locales/ru-RU.ts b/src/components/locale/locales/ru-RU.ts
index b8dc4ecaed0..20ed84b439e 100644
--- a/src/components/locale/locales/ru-RU.ts
+++ b/src/components/locale/locales/ru-RU.ts
@@ -34,6 +34,8 @@ export const ruRU: NzLocale = {
chooseDate: 'Выберите дату',
chooseTimePlease: 'Выберите время',
chooseDatePlease: 'Выберите дату',
+ chooseStartDatePlease: 'Дата начала',
+ chooseEndDatePlease: 'Дата окончания',
thisMoment: 'Сейчас',
today: 'Сегодня',
ok: 'Ок',
diff --git a/src/components/locale/locales/tr-TR.ts b/src/components/locale/locales/tr-TR.ts
index b5076ac1fc8..eff1f26303c 100644
--- a/src/components/locale/locales/tr-TR.ts
+++ b/src/components/locale/locales/tr-TR.ts
@@ -34,6 +34,8 @@ export const trTR: NzLocale = {
chooseDate: 'Tarih seçin',
chooseTimePlease: 'Saat seçin',
chooseDatePlease: 'Tarih seçin',
+ chooseStartDatePlease: 'Başlangıç tarihi',
+ chooseEndDatePlease: 'Bitiş tarihi',
thisMoment: 'Şimdi',
today: 'Bugün',
ok: 'Tamam',
diff --git a/src/components/locale/locales/zh-CN.ts b/src/components/locale/locales/zh-CN.ts
index 9984753a68e..53e2a4b9350 100644
--- a/src/components/locale/locales/zh-CN.ts
+++ b/src/components/locale/locales/zh-CN.ts
@@ -34,6 +34,8 @@ export const zhCN: NzLocale = {
chooseDate: '选择日期',
chooseTimePlease: '请选择时间',
chooseDatePlease: '请选择日期',
+ chooseStartDatePlease: '开始日期',
+ chooseEndDatePlease: '结束日期',
thisMoment: '此刻',
today: '今天',
ok: '确 定',
diff --git a/src/components/locale/locales/zh-TW.ts b/src/components/locale/locales/zh-TW.ts
index 70fc71de9ff..eb77e22b908 100644
--- a/src/components/locale/locales/zh-TW.ts
+++ b/src/components/locale/locales/zh-TW.ts
@@ -34,6 +34,8 @@ export const zhTW: NzLocale = {
chooseDate: '選擇日期',
chooseTimePlease: '请選擇時間',
chooseDatePlease: '请選擇日期',
+ chooseStartDatePlease: '開始日期',
+ chooseEndDatePlease: '結束日期',
thisMoment: '此刻',
today: '今天',
ok: '確 定',
diff --git a/src/components/locale/nz-locale.class.ts b/src/components/locale/nz-locale.class.ts
index c3ba09a5c17..824ba100a27 100644
--- a/src/components/locale/nz-locale.class.ts
+++ b/src/components/locale/nz-locale.class.ts
@@ -33,6 +33,8 @@ export class NzLocale {
chooseDate: string;
chooseTimePlease: string;
chooseDatePlease: string;
+ chooseStartDatePlease: string;
+ chooseEndDatePlease: string;
thisMoment: string;
today: string;
ok: string;
diff --git a/src/components/ng-zorro-antd.module.ts b/src/components/ng-zorro-antd.module.ts
index 1a8a8b3ce27..3a442499c0c 100644
--- a/src/components/ng-zorro-antd.module.ts
+++ b/src/components/ng-zorro-antd.module.ts
@@ -134,6 +134,7 @@ export { NzCascaderComponent } from './cascader/nz-cascader.component';
export { NzCheckboxGroupComponent } from './checkbox/nz-checkbox-group.component';
export { NzCheckboxComponent } from './checkbox/nz-checkbox.component';
export { NzDatePickerComponent } from './datepicker/nz-datepicker.component';
+export { NzRangePickerComponent } from './datepicker/nz-rangepicker.component';
export { NzFormControlComponent } from './form/nz-form-control.component';
export { NzFormExplainComponent } from './form/nz-form-explain.directive';
export { NzFormExtraDirective } from './form/nz-form-extra.directive';
diff --git a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-basic.component.ts b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-basic.component.ts
index 5adeef5fac8..b98665d8642 100644
--- a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-basic.component.ts
+++ b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-basic.component.ts
@@ -3,9 +3,17 @@ import { Component } from '@angular/core';
@Component({
selector: 'nz-demo-datepicker-basic',
template: `
- `,
+
+
+ `,
styles : []
})
export class NzDemoDatePickerBasicComponent {
_date = null;
+ _dateRange = [null, null];
+
+ constructor() {
+ }
+
}
diff --git a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disable-date.component.ts b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disable-date.component.ts
index 4c4e8ed62ca..5a12a9eb197 100644
--- a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disable-date.component.ts
+++ b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disable-date.component.ts
@@ -6,17 +6,20 @@ import * as moment from 'moment';
template: `
+
`,
styles : []
})
export class NzDemoDatePickerDisableDateComponent {
_date = null;
_moment = null;
- _disabledDate = function (current) {
+ _dateRange = [null, null];
+
+ _disabledDate(current: Date): boolean {
return current && current.getTime() > Date.now();
- };
+ }
- _disabledMonth = function (current) {
+ _disabledMonth(current: Date): boolean {
return current && moment(current).day(0).valueOf() > moment().valueOf();
- };
+ }
}
diff --git a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disabled.component.ts b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disabled.component.ts
index 36e28373028..49ae7f873c3 100644
--- a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disabled.component.ts
+++ b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-disabled.component.ts
@@ -3,9 +3,15 @@ import { Component } from '@angular/core';
@Component({
selector: 'nz-demo-datepicker-disabled',
template: `
- `,
+
+ `,
styles : []
})
export class NzDemoDatePickerDisabledComponent {
_date = new Date();
+ _dateRange = [new Date(), new Date(Date.now() + 3600 * 24 * 5 * 1000)];
+
+ constructor() {
+ }
+
}
diff --git a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-formatter.component.ts b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-formatter.component.ts
index 619ab596be3..de8b9a4d2a8 100644
--- a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-formatter.component.ts
+++ b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-formatter.component.ts
@@ -5,10 +5,16 @@ import { Component } from '@angular/core';
template: `
+
+
`,
styles : []
})
export class NzDemoDatePickerFormatterComponent {
_date = new Date();
_month = new Date();
+ _dateRange = [new Date(), new Date(Date.now() + 3600 * 24 * 5 * 1000)];
+ constructor() {
+ }
+
}
diff --git a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-size.component.ts b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-size.component.ts
index ff7980a611d..39d9c9b0734 100644
--- a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-size.component.ts
+++ b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-size.component.ts
@@ -3,11 +3,24 @@ import { Component } from '@angular/core';
@Component({
selector: 'nz-demo-datepicker-size',
template: `
-
-
- `,
+
+
+
+
+
+
+
+
+ `,
styles : []
})
export class NzDemoDatePickerSizeComponent {
+ size = 'default';
_date = null;
+ _month = null;
+ _dateRange = [null, null];
+
+ constructor() {
+ }
+
}
diff --git a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-time.component.ts b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-time.component.ts
index b1e3b0a2d6a..eadad00b594 100644
--- a/src/showcase/nz-demo-datepicker/nz-demo-datepicker-time.component.ts
+++ b/src/showcase/nz-demo-datepicker/nz-demo-datepicker-time.component.ts
@@ -3,10 +3,13 @@ import { Component } from '@angular/core';
@Component({
selector: 'nz-demo-datepicker-time',
template: `
- `,
+
+
+ `,
styles : []
})
export class NzDemoDatePickerTimeComponent {
_date = null;
+ _dateRange = [null, null];
}
diff --git a/src/showcase/nz-demo-datepicker/nz-demo-datepicker.html b/src/showcase/nz-demo-datepicker/nz-demo-datepicker.html
index e405346e067..aa25eac407d 100644
--- a/src/showcase/nz-demo-datepicker/nz-demo-datepicker.html
+++ b/src/showcase/nz-demo-datepicker/nz-demo-datepicker.html
@@ -28,7 +28,7 @@ 代码演示选择框的不可用状态。
-
+
可以设置 nzDisabledDate
方法,来约束开始和结束日期。
@@ -61,6 +61,64 @@
代码演示API
+
日期类组件包括以下三种形式。
+
+ - nz-datepicker
+ - nz-datepicker [nzMode='month']
+ - nz-rangepicker
+
+
共同的 API
+
+
+
+ 参数 |
+ 说明 |
+ 类型 |
+ 默认值 |
+
+
+
+
+ nzSize |
+ 输入框大小,large 高度为 32px,small 为 22px,默认是 28px |
+ String |
+ month |
+
+
+ nzFormat |
+ 展示的日期格式,配置参考
+ Moment.js文档
+ |
+ String |
+ "YYYY-MM-DD" |
+
+
+ nzDisabled |
+ 禁用 |
+ boolean |
+ false |
+
+
+ nzAllowClear |
+ 是否显示清除按钮 |
+ boolean |
+ true |
+
+
+ nzShowTime |
+ 时间选项,参见 nz-timepicker 参数 |
+ boolean | NzTimePickerInnerComponent |
+ null |
+
+
+ nzDisabledDate |
+ 用于禁用日期的回调函数,返回true表示禁用此日期 |
+ (Date) => boolean |
+ |
+
+
+
+
nz-datepicker
@@ -78,44 +136,43 @@ API
当前日期 |
- nzMode |
- 选择器模式, month 只选择到月份,day 选择到天 |
- String |
- "day" |
-
-
- nzSize |
- 输入框大小,large 高度为 32px,small 为 22px,默认是 28px |
- String |
- month |
-
-
- nzFormat |
- 展示的日期格式,配置参考
- Moment.js文档
- |
+ nzPlaceholder |
+ 输入框提示文字 |
String |
- "YYYY-MM-DD" |
-
-
- nzDisabled |
- 禁用 |
- bool |
- false |
-
-
- nzDisabledDate |
- 用于禁用日期的回调函数,返回true表示禁用此日期 |
- function(date) |
|
- nzShowTime |
- 时间选项,参见nz-timepicker参数 |
- |
- null |
+ nzMode |
+ 选择器模式, month 只选择到月份,day 选择到天 |
+ String |
+ "day" |
+
nz-rangepicker
+
+
+
+ 参数 |
+ 说明 |
+ 类型 |
+ 默认值 |
+
+
+
+
+ ngModel |
+ 展示日期 |
+ [Date, Date] |
+ 当前日期 |
+
+
+ nzPlaceholder |
+ 输入框提示文字 |
+ [String, String] |
+ |
+
+
+
diff --git a/src/showcase/nz-demo-locale/nz-demo-locale-all.component.ts b/src/showcase/nz-demo-locale/nz-demo-locale-all.component.ts
index 6dbc08c64fb..8244ca59944 100644
--- a/src/showcase/nz-demo-locale/nz-demo-locale-all.component.ts
+++ b/src/showcase/nz-demo-locale/nz-demo-locale-all.component.ts
@@ -78,6 +78,7 @@ export class NzDemoLocaleAllComponent implements OnInit {
+