Skip to content

Commit

Permalink
refactor(module:date-picker): refactor datepicker/rangepicker/weekpic…
Browse files Browse the repository at this point in the history
…ker against to ant-design (NG-ZORRO#1254)

close NG-ZORRO#1367 close NG-ZORRO#1267 close NG-ZORRO#1107 close NG-ZORRO#1097 close NG-ZORRO#1094 close NG-ZORRO#1079 close NG-ZORRO#1063 close NG-ZORRO#1060 close NG-ZORRO#1060 close NG-ZORRO#1046 close NG-ZORRO#1034 close NG-ZORRO#955 close NG-ZORRO#906 close NG-ZORRO#761 close NG-ZORRO#707 close NG-ZORRO#741 close NG-ZORRO#646 
* refactor(module:date-picker): TODO: complete all

complete more

complete date wrapper, need more flexiable with APIs of value select and change

complete parts of footer

the datepicker almost complete

commit to avoid side-effects with experiments

import the legacy timepicker, date-picker almost done

complete the common apis for datepicker

support all API for date-picker (which related to timepicker needs tebe complete)

split the date picker into more flexable components, pending for next range-picker

combine range-popup into date-popup, need self-testing

plug out the common abstract picker for both single/range picker

the range picker is almost done, but lots of work need todo still

soft remove legacy time-picker

compat with the latest time-picker

re-render the content of picker when open

add month-picker, need tobe done

done with month-picker & ready to develop week-picker

add support of week-picker

support ngModel for all pickers

complete parts of demos

support timePickerDisabled && timePickerDisabled (need testing)

support time-picker for date/range picker and more options like disabledDate/disabledTime

complete all demo and the chinese doc

add some testings for date-picker component

add more testing for date-picker component

fix problems of overlay's origin and backdrop with open

add testing for date-picker with ngModel

done testings for date-picker, start to add testings for range-picker

add testings for range picker

increase coverage of testings for date picker module

add testings for month-picker

increase more testing coverage

complete more testings for date picker module

* trimming relates for build packaging

* complete the zh/en documents

* support animations when hide/show

* fix(module:date-picker): change default to ngModel

* fix(module:date-picker): change default to ngModel

* fix the range's wrong default value setting

* make CandyDate changes into range picker testing

* aim to trigger ci

test(module:date-picker): fix month-picker test
  • Loading branch information
wilsoncook authored and vthinkxie committed May 15, 2018
1 parent 223d886 commit f8b4dee
Show file tree
Hide file tree
Showing 104 changed files with 7,449 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ sudo: required
dist: trusty
language: node_js
node_js:
- '6.10'
- '8.10'

env:
- TASK=pre-release
Expand Down
3 changes: 2 additions & 1 deletion components/auto-complete/nz-autocomplete.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,8 @@ describe('auto-complete', () => {
componentInstance.trigger.handleKeydown(TAB_EVENT);
fixture.detectChanges();
tick(500);

flush();
fixture.detectChanges();
expect(input.value)
.toBe('Downing Street');

Expand Down
1 change: 1 addition & 0 deletions components/components.less
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
@import "./checkbox/style/index.less";
@import "./collapse/style/index.less";
@import "./core/style/index.less";
@import "./date-picker/style/index.less";
@import "./divider/style/index.less";
@import "./dropdown/style/index.less";
@import "./form/style/index.less";
Expand Down
2 changes: 1 addition & 1 deletion components/core/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
.cdk-overlay-pane {
position: absolute;
pointer-events: auto;
// z-index: 1000; // Give an opportunity to the content own to manage their z-index such as Modal
z-index: 1000; // Give an opportunity to the content own to manage their z-index such as Modal
}

.box-shadow-left() {
Expand Down
2 changes: 2 additions & 0 deletions components/core/types/common-wrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Define a property that can also returned by called function
export type FunctionProp<T> = T | ((...args: any[]) => T) ; // tslint:disable-line:no-any
14 changes: 14 additions & 0 deletions components/core/util/check.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { TemplateRef, Type } from '@angular/core';

// tslint:disable-next-line:no-any
export function isNotNil(value: any): boolean {
return (typeof(value) !== 'undefined') && value !== null;
Expand Down Expand Up @@ -44,3 +46,15 @@ export function isEmpty(element: HTMLElement): boolean {
}
return true;
}

export function isNonEmptyString(value: any): boolean { // tslint:disable-line:no-any
return typeof value === 'string' && value !== '';
}

export function isTemplateRef(value: any): boolean { // tslint:disable-line:no-any
return value instanceof TemplateRef;
}

export function isComponent(value: any): boolean { // tslint:disable-line:no-any
return value instanceof Type;
}
7 changes: 6 additions & 1 deletion components/core/util/convert.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
// import { Input } from '@angular/core';
import { FunctionProp } from '../types/common-wrap';

export function toBoolean(value: boolean | string): boolean {
return coerceBooleanProperty(value);
Expand All @@ -9,6 +9,11 @@ export function toNumber<D>(value: number | string, fallback: D): number | D {
return coerceNumberProperty(value, fallback);
}

// Get the funciton-property type's value
export function valueFunctionProp<T>(prop: FunctionProp<T>, ...args: any[]): T { // tslint:disable-line: no-any
return typeof prop === 'function' ? prop(...args) : prop;
}

/**
* Input decorator that handle a prop to do get/set automatically with toBoolean
*
Expand Down
163 changes: 163 additions & 0 deletions components/date-picker/abstract-picker.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import {
Component,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
TemplateRef,
ViewChild
} from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';

import { FunctionProp } from '../core/types/common-wrap';
import { InputBoolean } from '../core/util/convert';
import { NzDatePickerI18nInterface } from '../i18n/nz-i18n.interface';
import { NzI18nService } from '../i18n/nz-i18n.service';
import { CandyDate } from './lib/candy-date';
import { NzPickerComponent } from './picker.component';
import { PickerResult, PickerResultRange, PickerResultSingle } from './standard-types';

const POPUP_STYLE_PATCH = { 'position': 'relative' }; // Aim to override antd's style to support overlay's position strategy (position:absolute will cause it not working beacuse the overlay can't get the height/width of it's content)

// @Component({ })

/**
* The base picker for all common APIs
*/
export abstract class AbstractPickerComponent implements OnInit, OnChanges, ControlValueAccessor {
// --- Common API
@Input() @InputBoolean() nzAllowClear: boolean = true;
@Input() @InputBoolean() nzAutoFocus: boolean = false;
@Input() @InputBoolean() nzDisabled: boolean = false;
@Input() @InputBoolean() nzOpen: boolean;
@Input() nzClassName: string;
@Input() nzDisabledDate: (d: Date) => boolean;
@Input() nzLocale: NzDatePickerI18nInterface;
@Input() nzPlaceholder: string | string[];
@Input() nzPopupStyle: object = POPUP_STYLE_PATCH;
@Input() nzDropdownClassName: string;
@Input() nzSize: 'large' | 'small';
@Input() nzStyle: object;
@Output() nzOnOpenChange = new EventEmitter<boolean>();

@Input() nzFormat: string;

@Input() nzValue: CompatibleValue;

@ViewChild(NzPickerComponent) protected picker: NzPickerComponent;

isRange: boolean = false; // Indicate whether the value is a range value

get realOpenState(): boolean {
return this.picker.animationOpenState;
} // Use picker's real open state to let re-render the picker's content when shown up

initValue(): void {
this.nzValue = this.isRange ? [] : null;
}

constructor(protected i18n: NzI18nService) {
}

ngOnInit(): void {
// Default locale (NOTE: Place here to assign default value due to the i18n'locale may change before ngOnInit)
if (!this.nzLocale) {
this.nzLocale = this.i18n.getLocaleData('DatePicker', {});
}

// Default value
this.initValue();

// Default placeholder
if (!this.nzPlaceholder) {
this.nzPlaceholder = this.isRange ? this.nzLocale.lang.rangePlaceholder : this.nzLocale.lang.placeholder;
}
}

ngOnChanges(changes: SimpleChanges): void {
if (changes.nzPopupStyle) { // Always assign the popup style patch
this.nzPopupStyle = this.nzPopupStyle ? { ...this.nzPopupStyle, ...POPUP_STYLE_PATCH } : POPUP_STYLE_PATCH;
}
}

closeOverlay(): void {
this.picker.hideOverlay();
}

/**
* Common handle for value changes
* @param value changed value
*/
onValueChange(value: CompatibleValue): void {
this.nzValue = value;
if (this.isRange) {
if ((this.nzValue as CandyDate[]).length) {
this.onChangeFn([ this.nzValue[ 0 ].nativeDate, this.nzValue[ 1 ].nativeDate ]);
} else {
this.onChangeFn([]);
}
} else {
if (this.nzValue) {
this.onChangeFn((this.nzValue as CandyDate).nativeDate);
} else {
this.onChangeFn(null);
}
}
this.onTouchedFn();
}

/**
* Triggered when overlayOpen changes (different with realOpenState)
* @param open The overlayOpen in picker component
*/
onOpenChange(open: boolean): void {
this.nzOnOpenChange.emit(open);
}

// ------------------------------------------------------------------------
// | Control value accessor implements
// ------------------------------------------------------------------------

// NOTE: onChangeFn/onTouchedFn will not be assigned if user not use as ngModel
onChangeFn: (val: CompatibleDate) => void = () => void 0;
onTouchedFn: () => void = () => void 0;

writeValue(value: CompatibleDate): void {
this.setValue(value);
}

registerOnChange(fn: any): void { // tslint:disable-line:no-any
this.onChangeFn = fn;
}

registerOnTouched(fn: any): void { // tslint:disable-line:no-any
this.onTouchedFn = fn;
}

setDisabledState(disabled: boolean): void {
this.nzDisabled = disabled;
}

// ------------------------------------------------------------------------
// | Internal methods
// ------------------------------------------------------------------------

private formatDate(date: CandyDate): string {
return date ? this.i18n.formatDateCompatible(date.nativeDate, this.nzFormat) : '';
}

// Safe way of setting value with default
private setValue(value: CompatibleDate): void {
if (this.isRange) {
this.nzValue = value ? (value as Date[]).map(val => new CandyDate(val)) : [];
} else {
this.nzValue = value ? new CandyDate(value as Date) : null;
}
}
}

export type CompatibleValue = CandyDate | CandyDate[];

export type CompatibleDate = Date | Date[];
Loading

0 comments on commit f8b4dee

Please sign in to comment.