Skip to content

Commit

Permalink
feat(module: date-picker): feat support date-picker ngmodel (#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
Guoyuanqiang authored and fisherspy committed Dec 29, 2018
1 parent 04df46a commit c1e6d11
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DatePickerViewModule } from './date-picker-view.module';
import { DatePickerOptions, DatePickerModule } from '../date-picker/index';
Expand All @@ -19,7 +20,7 @@ describe('DatePickerViewComponent', () => {
TestBed.configureTestingModule({
declarations: [TestDatePickerViewBasicComponent],
providers: [DatePickerOptions, LocaleProviderService, Toast],
imports: [DatePickerModule, DatePickerViewModule, LocaleProviderModule, ToastModule]
imports: [DatePickerModule, DatePickerViewModule, LocaleProviderModule, ToastModule, FormsModule]
}).compileComponents();
TestBed.overrideModule(DatePickerViewModule, {
set: { entryComponents: [ToastComponent] }
Expand Down Expand Up @@ -87,7 +88,7 @@ describe('DatePickerViewComponent', () => {
selector: 'test-date-picker-view-basic',
template: `
<DatePickerView [mode]="mode"
[value]="value1"
[ngModel]="value1"
[locale]="locale"
[maxDate]="maxDate"
[minDate]="minDate"
Expand All @@ -105,7 +106,7 @@ export class TestDatePickerViewBasicComponent {
maxDate = new Date(2031, 1, 1, 0, 0, 0);

onValueChange1(result) {
this.name1 = result;
this.value1 = new Date(result);
this.name1 = result.date;
this.value1 = result.date;
}
}
80 changes: 51 additions & 29 deletions components/date-picker-view/date-picker-view.component.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
import {
Component,
OnInit,
ViewEncapsulation,
Input,
OnInit,
Output,
EventEmitter,
Component,
OnChanges,
forwardRef,
HostBinding,
EventEmitter,
SimpleChanges,
AfterViewInit,
HostBinding
ViewEncapsulation
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { DatePickerComponent } from '../date-picker/date-picker.component';
import { Toast } from '../toast/toast.service';

@Component({
selector: 'DatePickerView, nzm-date-picker-view',
templateUrl: './date-picker-view.component.html',
encapsulation: ViewEncapsulation.None,
providers: [Toast]
providers: [
Toast,
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatePickerViewComponent),
multi: true
}
]
})
export class DatePickerViewComponent extends DatePickerComponent implements OnInit, AfterViewInit, OnChanges {
export class DatePickerViewComponent extends DatePickerComponent implements OnInit, AfterViewInit, OnChanges, ControlValueAccessor {
@Input()
mode: string = 'date';
@Input()
Expand Down Expand Up @@ -51,7 +60,38 @@ export class DatePickerViewComponent extends DatePickerComponent implements OnIn
@HostBinding('class.am-picker')
amPicker = true;

init() {
reloadPicker() {
if (this.currentPicker) {
const self = this;
setTimeout(() => {
self.selectedTarget.forEach((item, i) => {
self.currentPicker.children[i].children[2].style.transition = 'transform .3s';
const index = parseInt(item.currentY, 0);
self.currentPicker.children[i].children[2].style.transform = `translateY(${index * self.lineHeight}px)`;
});
}, 0);
}
}

writeValue(value: Date): void {
if (value) {
this.value = value;
}
}

registerOnChange(fn: (_: Date) => {}): void {
this.ngModelOnChange = fn;
}

registerOnTouched(fn: () => {}): void {
this.ngModelOnTouched = fn;
}

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

optionInit() {
this.options.mode = this.mode;
this.options.minDate = this.minDate;
this.options.maxDate = this.maxDate;
Expand All @@ -68,30 +108,10 @@ export class DatePickerViewComponent extends DatePickerComponent implements OnIn
return parseInt(item, 0);
});
}
if (!this.checkTime() && this.options.showErrorToast) {
setTimeout(() => {
Toast.fail(this.errorMessage, this.options.showErrorToastInterval);
}, 0);
}
this.initResult();
this.initReady();
this.getInitValueIndex();
}

reloadPicker() {
if (this.currentPicker) {
const self = this;
setTimeout(() => {
self.selectedTarget.forEach((item, i) => {
self.currentPicker.children[i].children[2].style.transition = 'transform .3s';
const index = parseInt(item.currentY, 0);
self.currentPicker.children[i].children[2].style.transform = `translateY(${index * self.lineHeight}px)`;
});
}, 0);
}
}

ngOnInit() {
this.optionInit();
this.localeProvider();
}

Expand All @@ -114,11 +134,13 @@ export class DatePickerViewComponent extends DatePickerComponent implements OnIn
this.judgeEqualArray(this.currentTime, this.min_date, this.currentTime.length) ||
this.judgeTime(this.currentTime, this.max_date)
) {
this.optionInit();
this.init();
}
}

if (changes.mode || changes.minDate || changes.maxDate || changes.disabled || changes.locale) {
this.optionInit();
this.init();
}
}
Expand Down
3 changes: 2 additions & 1 deletion components/date-picker-view/date-picker-view.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { DatePickerViewComponent } from './date-picker-view.component';
import { LocaleProviderModule } from '../locale-provider/locale-provider.module';
Expand All @@ -7,7 +8,7 @@ import { ToastModule } from '../toast/toast.module';
import { ToastComponent } from '../toast/toast.component';

@NgModule({
imports: [CommonModule, DatePickerModule, LocaleProviderModule, ToastModule],
imports: [CommonModule, DatePickerModule, LocaleProviderModule, ToastModule, FormsModule],
exports: [DatePickerViewComponent],
declarations: [DatePickerViewComponent],
entryComponents: [ToastComponent],
Expand Down
16 changes: 10 additions & 6 deletions components/date-picker-view/demo/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Component } from '@angular/core';
@Component({
selector: 'demo-date-picker-view-basic',
template: `
<div class="sub-title">Start datetime {{name1}}</div>
<DatePickerView [value]="value1" (onValueChange)="onValueChange1($event)"></DatePickerView>
<div class="sub-title">Start datetime {{getDate(value1)}}</div>
<DatePickerView [(ngModel)]="value1" (onValueChange)="onValueChange($event)"></DatePickerView>
`,
styles: [
`
Expand All @@ -19,7 +19,7 @@ export class DemoDatePickerViewBasicComponent {
name2 = '选择';
mode = 'date';

value1 = new Date(1918, 8, 15, 8, 0);
value1 = new Date(2018, 8, 15, 8, 0);
value2 = new Date();

currentDateFormat(date, format: string = 'yyyy-mm-dd HH:MM:ss'): any {
Expand All @@ -33,7 +33,7 @@ export class DemoDatePickerViewBasicComponent {
.replace('ss', pad(date.getSeconds()));
}

onValueChange1(result) {
getDate(result) {
let format = 'yyyy-mm-dd';
if (this.mode === 'year') {
format = 'yyyy';
Expand All @@ -46,8 +46,12 @@ export class DemoDatePickerViewBasicComponent {
} else {
format = 'HH:MM';
}
this.name1 = this.currentDateFormat(result, format);
this.value1 = new Date(result);
this.value1 = result;
return this.currentDateFormat(result, format);
}

onValueChange(event) {
console.log(event);
}

formatIt(date: Date, form: string) {
Expand Down
2 changes: 1 addition & 1 deletion components/date-picker-view/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ DatePickerView's functions like DatePicker, but it is rendered directly in the a
Properties | Descrition | Type | Default
-----------|------------|------|--------
| mode | mode value, can be a `date` or `time` or `datetime` or `year` or `month` | String | `date` |
| value | the currently selected value | Date | - |
| ngModel | the currently selected value | Date | - |
| minDate | minimum date | Date | 2000-1-1 |
| maxDate | maximum date | Date | 2030-1-1 |
| locale | international, can override the configuration of the global `[LocaleProvider](https://ng.mobile.ant.design/components/locale-provider/en)` | Object: {DatePickerLocale: {year, month, day, hour, minute, am?, pm?}, okText, dismissText} | - |
Expand Down
2 changes: 1 addition & 1 deletion components/date-picker-view/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ DatePickerView 的功能类似于 DatePicker ,但它是直接渲染在区域
属性 | 说明 | 类型 | 默认值
----|-----|------|------
| mode | 日期选择的类型, 可以是日期`date`,时间`time`,日期+时间`datetime`,年`year`,月`month` | String | `date` |
| value | 当前选中时间 | Date ||
| ngModel | 当前选中时间 | Date ||
| minDate | 最小可选日期 | Date | 2000-1-1 |
| maxDate | 最大可选日期 | Date | 2030-1-1 |
| locale | 国际化,可覆盖全局`[LocaleProvider](https://ng.mobile.ant.design/components/locale-provider/zh)`的配置 | Object: {DatePickerLocale: {year, month, day, hour, minute, am?, pm?}, okText, dismissText } | - |
Expand Down
1 change: 1 addition & 0 deletions components/date-picker/date-picker-options.provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ export class DatePickerOptions implements DatePickerOptionsInterface {
onValueChange: EventEmitter<any> = new EventEmitter();
onChange: EventEmitter<any> = new EventEmitter();
hidePicker: () => void;
updateNgModel?: (value: Date) => void;
}
30 changes: 25 additions & 5 deletions components/date-picker/date-picker.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export class DatePickerComponent implements OnInit, OnDestroy, AfterViewInit {
unsubscribe$ = new Subject<void>();
Velocity = velocity.getVelocity();
errorMessage = '';
ngModelOnChange: (value: Date) => {};
ngModelOnTouched: () => {};

@ViewChild('picker', { read: ViewContainerRef })
picker: ViewContainerRef;
Expand Down Expand Up @@ -155,16 +157,34 @@ export class DatePickerComponent implements OnInit, OnDestroy, AfterViewInit {
if (this.judgeTime(this.current_time, this.max_date)) {
this.currentTime = this.current_time = this.max_date.slice(0, this.indexArray.length);
this.resultArr = this.current_time;
this.options.onValueChange.emit(this.handleReslut());
this.options.onValueChange.emit({date: this.handleReslut(), index: event.target.id});
if (this.options.updateNgModel) {
this.options.updateNgModel(this.handleReslut());
}
if (this.ngModelOnChange) {
this.ngModelOnChange(this.handleReslut());
}
this.init();
} else if (this.judgeTime(this.min_date, this.current_time)) {
this.currentTime = this.current_time = this.min_date.slice(0, this.indexArray.length);
this.resultArr = this.currentTime;
this.options.onValueChange.emit(this.handleReslut());
this.options.onValueChange.emit({date: this.handleReslut(), index: event.target.id});
if (this.options.updateNgModel) {
this.options.updateNgModel(this.handleReslut());
}
if (this.ngModelOnChange) {
this.ngModelOnChange(this.handleReslut());
}
this.init();
} else {
this.setCurrentSelected(0, this.differY < 0, this.index);
this.options.onValueChange.emit(this.handleReslut());
this.options.onValueChange.emit({date: this.handleReslut(), index: event.target.id});
if (this.options.updateNgModel) {
this.options.updateNgModel(this.handleReslut());
}
if (this.ngModelOnChange) {
this.ngModelOnChange(this.handleReslut());
}
}
}

Expand Down Expand Up @@ -337,8 +357,8 @@ export class DatePickerComponent implements OnInit, OnDestroy, AfterViewInit {
current_time[0],
current_time[1],
current_time[2],
current_time[3],
current_time[4]
current_time[3] || 0,
current_time[4] || 0
).getTime();
if (curT < minT) {
this.currentTime = this.current_time;
Expand Down
55 changes: 43 additions & 12 deletions components/date-picker/date-picker.directive.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
import {
Directive,
Input,
Output,
OnInit,
Injector,
OnChanges,
OnDestroy,
Directive,
forwardRef,
ElementRef,
EventEmitter,
HostListener,
ViewContainerRef,
ComponentRef,
OnDestroy,
ElementRef,
OnChanges,
OnInit,
Injector,
ComponentFactoryResolver,
SimpleChanges,
ComponentFactory,
SimpleChanges
ViewContainerRef,
ComponentFactoryResolver
} from '@angular/core';
import { DatePickerComponent } from './date-picker.component';
import { DatePickerOptions } from './date-picker-options.provider';

import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Directive({
selector: '[DatePicker]'
selector: '[DatePicker]',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatePickerDirective),
multi: true
}
]
})
export class DatePickerDirective implements OnDestroy, OnChanges, OnInit {
export class DatePickerDirective implements OnDestroy, OnChanges, OnInit, ControlValueAccessor {
picker: ComponentRef<DatePickerComponent>;
private _eventListeners: Array<() => void> = [];
private _ngModelOnChange: (value: Date) => {};
private _ngModelOnTouched: () => {};

@Input()
isOpen: boolean;
Expand Down Expand Up @@ -90,6 +100,11 @@ export class DatePickerDirective implements OnDestroy, OnChanges, OnInit {
Object.assign(options, this._defaultOptions, {
hidePicker: (event): void => {
this.hidePicker();
},
updateNgModel: (value: Date): void => {
if (this._ngModelOnChange) {
this._ngModelOnChange(value);
}
}
});

Expand Down Expand Up @@ -147,6 +162,22 @@ export class DatePickerDirective implements OnDestroy, OnChanges, OnInit {
}
}

writeValue(value: Date): void {
this.value = value;
}

registerOnChange(fn: (_: Date) => {}): void {
this._ngModelOnChange = fn;
}

registerOnTouched(fn: () => {}): void {
this._ngModelOnTouched = fn;
}

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

ngOnInit(): void {
this.onVisibleChange.emit(false);
}
Expand Down
Loading

0 comments on commit c1e6d11

Please sign in to comment.