From 92b92d6628657fbb05e60c417810e40a5a15b6cc Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Tue, 4 Oct 2016 18:18:07 +0530 Subject: [PATCH 1/8] update issues. --- src/demo-app/index.html | 2 +- src/demo-app/select/select-demo.html | 9 ++++++++- src/demo-app/select/select-demo.ts | 11 +++++++++++ src/lib/datepicker/datepicker.ts | 1 + src/lib/select/select.ts | 4 ++++ 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/demo-app/index.html b/src/demo-app/index.html index 6d8c1b0f8..ccfe9751c 100644 --- a/src/demo-app/index.html +++ b/src/demo-app/index.html @@ -1,7 +1,7 @@  - + diff --git a/src/demo-app/select/select-demo.html b/src/demo-app/select/select-demo.html index 849b0de6e..1007d59ea 100644 --- a/src/demo-app/select/select-demo.html +++ b/src/demo-app/select/select-demo.html @@ -3,9 +3,16 @@

Select Demo


Basic Select

+
{{item}}
+ + +
-- Select City -- - {{i.name}} + {{i.name}}

Static Select

diff --git a/src/demo-app/select/select-demo.ts b/src/demo-app/select/select-demo.ts index dc55d2ffc..c877615f4 100644 --- a/src/demo-app/select/select-demo.ts +++ b/src/demo-app/select/select-demo.ts @@ -6,6 +6,17 @@ import { Component } from '@angular/core'; templateUrl: 'select-demo.html' }) export class SelectDemo { + constructor() { + setTimeout(() => { + this.items.push({ name: 'Manjalpur', value: '7', disabled: false }); + this.items.push({ name: 'Sitabag', value: '8', disabled: false }); + this.items.push({ name: 'Vasna', value: '9', disabled: false, selected: true }); + this.items.push({ name: 'Gorva', value: '10', disabled: false }); + }, 3000); + setTimeout(() => { + //this.item = '8'; + }, 5000); + } private items: Array = [ { name: 'Vadodara', value: '1', disabled: false }, diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 6c1d89c12..4e96e8966 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -93,6 +93,7 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { private _onTouchedCallback: () => void = noop; private _onChangeCallback: (_: any) => void = noop; + private isYearpickerVisible: boolean; private isDatepickerVisible: boolean; private isCalendarVisible: boolean; private isHoursVisible: boolean = true; diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts index 85dd090fc..9b94f4b3b 100644 --- a/src/lib/select/select.ts +++ b/src/lib/select/select.ts @@ -157,6 +157,10 @@ export class Md2Select implements AfterContentChecked, ControlValueAccessor { if (this.selected && this.selectedValue !== this.selected.content) { this.selectedValue = this.selected.content; } + //let opt = this._options.filter(o => this.equals(o.value, this.value))[0]; + //if (opt && !this.equals(this.selected, opt)) { + // this.selectedValue = opt.content; + //} } /** From cb955cace3959ade54de5722eebf635ae6b31eaf Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Wed, 5 Oct 2016 11:25:50 +0530 Subject: [PATCH 2/8] feat: BooleanFieldValue annotation --- src/lib/core/annotations/field-value.ts | 31 +++++++++++++++++++++++++ src/lib/core/core.ts | 3 +++ src/lib/datepicker/datepicker.ts | 11 ++++----- 3 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 src/lib/core/annotations/field-value.ts diff --git a/src/lib/core/annotations/field-value.ts b/src/lib/core/annotations/field-value.ts new file mode 100644 index 000000000..46001c981 --- /dev/null +++ b/src/lib/core/annotations/field-value.ts @@ -0,0 +1,31 @@ +/** + * Annotation Factory that allows HTML style boolean attributes. For example, + * a field declared like this: + + * @Directive({ selector: 'component' }) class MyComponent { + * @Input() @BooleanFieldValueFactory() myField: boolean; + * } + * + * You could set it up this way: + * + * or: + * + * @deprecated + */ +function booleanFieldValueFactory() { + return function booleanFieldValueMetadata(target: any, key: string): void { + const defaultValue = target[key]; + const localKey = `__md_private_symbol_${key}`; + target[localKey] = defaultValue; + + Object.defineProperty(target, key, { + get() { return (this)[localKey]; }, + set(value: boolean) { + (this)[localKey] = value != null && `${value}` !== 'false'; + } + }); + }; +} + + +export { booleanFieldValueFactory as BooleanFieldValue }; diff --git a/src/lib/core/core.ts b/src/lib/core/core.ts index e62489b26..0afb31a21 100644 --- a/src/lib/core/core.ts +++ b/src/lib/core/core.ts @@ -36,6 +36,9 @@ export { applyCssTransform } from './style/apply-transform'; // Error export { MdError } from './errors/error'; +// Annotations. +export { BooleanFieldValue } from './annotations/field-value'; + // Misc export { ComponentType } from './overlay/generic-component-type'; diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 4e96e8966..0c338a54f 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -19,7 +19,10 @@ import { import { CommonModule } from '@angular/common'; import { Md2DateUtil } from './dateUtil'; -import { KeyCodes } from '../core/core'; +import { + BooleanFieldValue, + KeyCodes +} from '../core/core'; export interface IDay { year: number; @@ -89,7 +92,6 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { //private mouseUpListener: any; private _value: Date = null; - private _disabled: boolean = false; private _onTouchedCallback: () => void = noop; private _onChangeCallback: (_: any) => void = noop; @@ -128,10 +130,7 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { @Output() change: EventEmitter = new EventEmitter(); @Input() type: 'date' | 'time' | 'datetime' = 'date'; - @Input() get disabled(): boolean { return this._disabled; } - set disabled(value) { - this._disabled = (value !== null && value !== false) ? true : null; - } + @Input() @BooleanFieldValue() disabled: boolean = false; @Input() name: string = ''; @Input() id: string = 'md2-datepicker-' + (++nextId); @Input() class: string; From 3c89bc775daa5aa0060b5497579937e2b6727873 Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Wed, 5 Oct 2016 12:37:03 +0530 Subject: [PATCH 3/8] update demo server port. --- tools/gulp/task_helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gulp/task_helpers.ts b/tools/gulp/task_helpers.ts index fa21f9915..415592761 100644 --- a/tools/gulp/task_helpers.ts +++ b/tools/gulp/task_helpers.ts @@ -178,7 +178,7 @@ export function serverTask(liveReload: boolean = true, const stream = gulp.src('dist').pipe(gulpServer({ livereload: liveReload, fallback: 'index.html', - port: 4200 + port: 3000 })); if (streamCallback) { From 5af3d3afba92845b87f5c91e3f9eef5999a54709 Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Wed, 5 Oct 2016 12:42:26 +0530 Subject: [PATCH 4/8] update demo app server port --- tools/gulp/task_helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gulp/task_helpers.ts b/tools/gulp/task_helpers.ts index 415592761..a991e5ae1 100644 --- a/tools/gulp/task_helpers.ts +++ b/tools/gulp/task_helpers.ts @@ -178,7 +178,7 @@ export function serverTask(liveReload: boolean = true, const stream = gulp.src('dist').pipe(gulpServer({ livereload: liveReload, fallback: 'index.html', - port: 3000 + port: 3200 })); if (streamCallback) { From 2d4cba9834049355c2730305b23eb9a9e203787b Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Wed, 5 Oct 2016 12:42:46 +0530 Subject: [PATCH 5/8] update select component --- src/lib/select/select.ts | 8 +- src/lib/select/selectNew.ts | 197 ++++++++++++++++++++++++++++++++++++ 2 files changed, 201 insertions(+), 4 deletions(-) create mode 100644 src/lib/select/selectNew.ts diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts index 9b94f4b3b..a25065343 100644 --- a/src/lib/select/select.ts +++ b/src/lib/select/select.ts @@ -154,13 +154,13 @@ export class Md2Select implements AfterContentChecked, ControlValueAccessor { constructor(public element: ElementRef) { } ngAfterContentChecked() { + let opt = this._options.filter(o => this.equals(o.value, this.value))[0]; + if (opt && !this.equals(this.selected, opt)) { + this.selectedValue = opt.content; + } if (this.selected && this.selectedValue !== this.selected.content) { this.selectedValue = this.selected.content; } - //let opt = this._options.filter(o => this.equals(o.value, this.value))[0]; - //if (opt && !this.equals(this.selected, opt)) { - // this.selectedValue = opt.content; - //} } /** diff --git a/src/lib/select/selectNew.ts b/src/lib/select/selectNew.ts new file mode 100644 index 000000000..9739e56be --- /dev/null +++ b/src/lib/select/selectNew.ts @@ -0,0 +1,197 @@ +import { + Component, + Directive, + ElementRef, + HostListener, + Input, + Output, + EventEmitter, + forwardRef, + ViewEncapsulation, + NgModule, + ModuleWithProviders +} from '@angular/core'; +import { + NG_VALUE_ACCESSOR, + ControlValueAccessor, + FormsModule +} from '@angular/forms'; +import { CommonModule } from '@angular/common'; + +import { KeyCodes } from '../core/core'; + +const noop = () => { }; + +let nextId = 0; + +export const MD2_SELECT_CONTROL_VALUE_ACCESSOR: any = { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => Md2Select), + multi: true +}; + +@Component({ + moduleId: module.id, + selector: 'md2-select', + template: 'I am a select', + styles: [''], + providers: [MD2_SELECT_CONTROL_VALUE_ACCESSOR], + host: { + 'role': 'select', + '[id]': 'id', + '[class.md2-select-disabled]': 'disabled', + '[tabindex]': 'disabled ? -1 : tabindex', + }, + encapsulation: ViewEncapsulation.None +}) +export class Md2Select implements ControlValueAccessor { + + constructor() { } + + private _value: Date = null; + private _disabled: boolean = false; + private _onTouchedCallback: () => void = noop; + private _onChangeCallback: (_: any) => void = noop; + + private isMenuVisible: boolean = false; + + @Output() change: EventEmitter = new EventEmitter(); + + @Input() + get disabled(): boolean { return this._disabled; } + set disabled(value) { + this._disabled = (value !== null && value !== false) ? true : null; + } + @Input() id: string = 'md2-select-' + (++nextId); + @Input() placeholder: string; + @Input() tabindex: number = 0; + + @Input() + get value(): any { return this._value; } + set value(value: any) { + if (value !== this._value) { + this._value = value; + this._onChangeCallback(value); + this.change.emit(value); + } + } + + @HostListener('click', ['$event']) + private onClick(event: MouseEvent) { + if (this.disabled) { + event.stopPropagation(); + event.preventDefault(); + return; + } + } + + @HostListener('keydown', ['$event']) + private onKeyDown(event: KeyboardEvent) { + if (this.disabled) { return; } + + if (this.isMenuVisible) { + event.preventDefault(); + event.stopPropagation(); + + switch (event.keyCode) { + case KeyCodes.TAB: + case KeyCodes.ESCAPE: this.onBlur(); break; + } + // switch (event.keyCode) { + // case KeyCodes.ENTER: + // case KeyCodes.SPACE: this.setDate(this.displayDate); break; + + // case KeyCodes.RIGHT_ARROW: this.displayDate = this.dateUtil.incrementDays(displayDate, 1); break; + // case KeyCodes.LEFT_ARROW: this.displayDate = this.dateUtil.incrementDays(displayDate, -1); break; + + // case KeyCodes.PAGE_DOWN: this.displayDate = this.dateUtil.incrementMonths(displayDate, 1); break; + // case KeyCodes.PAGE_UP: this.displayDate = this.dateUtil.incrementMonths(displayDate, -1); break; + + // case KeyCodes.DOWN_ARROW: this.displayDate = this.dateUtil.incrementDays(displayDate, 7); break; + // case KeyCodes.UP_ARROW: this.displayDate = this.dateUtil.incrementDays(displayDate, -7); break; + + // case KeyCodes.HOME: this.displayDate = this.dateUtil.getFirstDateOfMonth(displayDate); break; + // case KeyCodes.END: this.displayDate = this.dateUtil.getLastDateOfMonth(displayDate); break; + //} + } + } + + @HostListener('blur') + private onBlur() { this.isMenuVisible = false; } + + writeValue(value: any): void { this.value = value; } + + registerOnChange(fn: any) { this._onChangeCallback = fn; } + + registerOnTouched(fn: any) { this._onTouchedCallback = fn; } + +} + +@Component({ + moduleId: module.id, + selector: 'md2-optgroup', + template: ``, + styles: [''], + host: { + }, + encapsulation: ViewEncapsulation.None +}) +export class Md2Optgroup { + + private _disabled: any; + + @Input() label: string; + + @Input() + get disabled(): boolean { return this._disabled; } + set disabled(value) { + this._disabled = (value !== null && value !== false) ? true : null; + } +} + +@Directive({ selector: 'md2-option' }) +export class Md2Option { + constructor() { } + + private _value: any; + private _disabled: any; + private _selected: any; + + @Input() label: string; + + @Input() + get disabled(): boolean { return this._disabled; } + set disabled(value) { + this._disabled = (value !== null && value !== false) ? true : null; + } + + @Input() + get selected(): boolean { return this._selected; } + set selected(value) { + this._selected = (value !== null && value !== false) ? true : null; + } + + @Input() + get value(): any { return this._value; } + set value(value: any) { + if (value !== this._value) { + this._value = value; + } + } +} + +export const MD2_SELECT_DIRECTIVES = [Md2Select, Md2Optgroup, Md2Option]; + +@NgModule({ + declarations: MD2_SELECT_DIRECTIVES, + imports: [CommonModule, FormsModule], + exports: MD2_SELECT_DIRECTIVES, +}) +export class Md2SelectModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: Md2SelectModule, + providers: [] + }; + } +} From 69ee0bee55cfcb65b9a029c0c74eb9c33e1e5e2b Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Thu, 6 Oct 2016 15:43:58 +0530 Subject: [PATCH 6/8] feat(datepicker) year selection --- src/lib/datepicker/datepicker.html | 134 ++++++++++++++++------------- src/lib/datepicker/datepicker.scss | 17 +++- src/lib/datepicker/datepicker.ts | 77 +++++++++++++++-- 3 files changed, 158 insertions(+), 70 deletions(-) diff --git a/src/lib/datepicker/datepicker.html b/src/lib/datepicker/datepicker.html index d204dfc16..40e6b2184 100644 --- a/src/lib/datepicker/datepicker.html +++ b/src/lib/datepicker/datepicker.html @@ -21,9 +21,11 @@
{{displayDay.year}} + [class.active]="isYearsVisible" + [class.hidden]="type==='time'" + (click)="showYear()">{{displayDay.year}} {{displayDay.day.substr(0, 3)}}, {{displayDay.month.substr(0, 3)}} {{displayDay.date}}
-
-
-
- - - -
-
- - - -
-
{{displayDay.month}} {{displayDay.year}}
+
+
+
{{y}}
- - - - - - - -
{{d.substr(0, 1)}}
-
{{d.dateObj.day}}
-
-
- -
- - - - - - - - -
-
-
{{h.hour}}
+
+
+
+
+ + + +
+
+ + + +
+
{{displayDay.month}} {{displayDay.year}}
+
+ + + + + + + +
{{d.substr(0, 1)}}
+
{{d.dateObj.day}}
+
-
-
{{m.minute}}
+
+ +
+ + + + + + + + +
+
+
{{h.hour}}
+
+
+
{{m.minute}}
+
diff --git a/src/lib/datepicker/datepicker.scss b/src/lib/datepicker/datepicker.scss index 711a73030..82c78d861 100644 --- a/src/lib/datepicker/datepicker.scss +++ b/src/lib/datepicker/datepicker.scss @@ -15,11 +15,11 @@ md2-datepicker.md2-datepicker-disabled:focus .md2-datepicker-placeholder { color .md2-datepicker-wrapper { position: absolute; top: 0; left: 0; display: inline-block; width: 300px; border-radius: 2px; background-color: #fff; z-index: 10; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4); transform: scale(0); transform-origin: left top; transition: 150ms; -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .md2-datepicker-wrapper.active { transform: scale(1); } .md2-datepicker-header { display: block; padding: 20px; color: #fff; font-size: 28px; line-height: 28px; font-weight: 500; background: #2196f3; box-sizing: border-box; } -.md2-datepicker-year { display: block; height: 16px; margin: 0 0 10px; font-size: 16px; line-height: 16px; opacity: 0.7; } -.md2-datepicker-year.active { opacity: 1; } +.md2-datepicker-year { display: block; height: 16px; margin: 0 0 10px; font-size: 16px; line-height: 16px; opacity: 0.7; cursor: pointer; } +.md2-datepicker-year.active { opacity: 1; pointer-events: none; } .md2-datepicker-year.hidden { display: none; } .md2-datepicker-date { cursor: pointer; opacity: 0.7; } -.md2-datepicker-date.active { opacity: 1; } +.md2-datepicker-date.active { opacity: 1; pointer-events: none; } .md2-datepicker-date.hidden { display: none; } .md2-datepicker-time { display: inline-block; padding-left: 10px; cursor: pointer; opacity: 0.7; } .md2-datepicker-time.active { opacity: 1; } @@ -29,12 +29,21 @@ md2-datepicker.md2-datepicker-disabled:focus .md2-datepicker-placeholder { color .md2-datepicker-time.active .md2-datepicker-hour, .md2-datepicker-time.active .md2-datepicker-minute { opacity: 0.7; } .md2-datepicker-time.active .md2-datepicker-hour.active, -.md2-datepicker-time.active .md2-datepicker-minute.active { opacity: 1; } +.md2-datepicker-time.active .md2-datepicker-minute.active { opacity: 1; pointer-events: none; } .md2-datepicker-body { position: relative; width: 100%; height: 300px; overflow: hidden; } .md2-datepicker-footer { text-align: right; } .md2-datepicker-footer .md2-button { display: inline-block; min-width: 64px; margin: 4px 8px 8px 0px; padding: 0 12px; font-size: 14px; color: #2196f3; line-height: 36px; text-align: center; text-transform: uppercase; border-radius: 2px; cursor: pointer; box-sizing: border-box; transition: all 450ms cubic-bezier(0.23, 1, 0.32, 1); } .md2-datepicker-footer .md2-button:hover { background: #ebebeb; } +.md2-years { position: absolute; top: 10px; right: 100%; bottom: 10px; display: block; width: 100%; line-height: 40px; background: #fff; overflow-x: hidden; overflow-y: auto; transition: 300ms; } +.md2-years.active { right: 0; } +.md2-years .md2-years-wrapper { display: flex; flex-direction: column; justify-content: center; min-height: 100%; } +.md2-years .md2-year { position: relative; display: block; margin: 0 auto; padding: 0; font-size: 17px; font-weight: 400; text-align: center; cursor: pointer; } +.md2-years .md2-year.selected { color: #2196f3; font-size: 26px; font-weight: 500; } + +.md2-datepicker-container { position: absolute; top: 0; left: 100%; display: block; width: 100%; transition: 300ms; } +.md2-datepicker-container.active { left: 0; } + .md2-calendar { position: absolute; right: 100%; display: block; width: 100%; font-size: 12px; font-weight: 400; text-align: center; transition: 300ms; } .md2-calendar.active { right: 0; } .md2-calendar-controls { position: relative; display: block; height: 48px; text-align: left; } diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 0c338a54f..b6bc8e58d 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -78,8 +78,8 @@ export const MD2_DATEPICKER_CONTROL_VALUE_ACCESSOR: any = { export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { constructor(private dateUtil: Md2DateUtil, private element: ElementRef) { + this.getYears(); this.generateClock(); - this.isCalendarVisible; //this.mouseMoveListener = (event: MouseEvent) => { this.onMouseMoveClock(event); }; //this.mouseUpListener = (event: MouseEvent) => { this.onMouseUpClock(event); }; } @@ -95,8 +95,8 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { private _onTouchedCallback: () => void = noop; private _onChangeCallback: (_: any) => void = noop; - private isYearpickerVisible: boolean; private isDatepickerVisible: boolean; + private isYearsVisible: boolean; private isCalendarVisible: boolean; private isHoursVisible: boolean = true; @@ -109,6 +109,7 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { private currMonth: number = 2; private nextMonth: number = 3; + private years: Array = []; private dates: Array = []; private today: Date = new Date(); private _displayDate: Date = null; @@ -144,10 +145,12 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { @Input() set min(value: string) { this._minDate = new Date(value); this._minDate.setHours(0, 0, 0, 0); + this.getYears(); } @Input() set max(value: string) { this._maxDate = new Date(value); this._maxDate.setHours(0, 0, 0, 0); + this.getYears(); } get value(): any { return this._value; } @@ -228,7 +231,24 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { case KeyCodes.ESCAPE: this.onBlur(); break; } let displayDate = this.displayDate; - if (this.isCalendarVisible) { + if (this.isYearsVisible) { + switch (event.keyCode) { + case KeyCodes.ENTER: + case KeyCodes.SPACE: this.onClickOk(); break; + + case KeyCodes.DOWN_ARROW: + if (this.displayDate.getFullYear() === (this.today.getFullYear() + 100)) break; + this.displayDate = this.dateUtil.incrementYears(displayDate, 1); + this._scrollToSelectedYear(); + break; + case KeyCodes.UP_ARROW: + if (this.displayDate.getFullYear() === 1900) break; + this.displayDate = this.dateUtil.incrementYears(displayDate, -1); + this._scrollToSelectedYear(); + break; + } + + } else if (this.isCalendarVisible) { switch (event.keyCode) { case KeyCodes.ENTER: case KeyCodes.SPACE: this.setDate(this.displayDate); break; @@ -280,9 +300,47 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { @HostListener('blur') private onBlur() { this.isDatepickerVisible = false; + this.isYearsVisible = false; this.isCalendarVisible = this.type !== 'time' ? true : false; this.isHoursVisible = true; } + /** + * Display Years + */ + private showYear() { + this.isYearsVisible = true; + this.isCalendarVisible = true; + this._scrollToSelectedYear(); + } + + private getYears() { + let startYear = this._minDate ? this._minDate.getFullYear() : 1900, + endYear = this._maxDate ? this._maxDate.getFullYear() : this.today.getFullYear() + 100; + this.years = []; + for (let i = startYear; i <= endYear; i++) { + this.years.push(i); + } + } + + private _scrollToSelectedYear() { + setTimeout(() => { + let yearContainer = this.element.nativeElement.querySelector('.md2-years'), + selectedYear = this.element.nativeElement.querySelector('.md2-year.selected'); + yearContainer.scrollTop = (selectedYear.offsetTop + 20) - yearContainer.clientHeight / 2; + }, 0); + } + + /** + * select year + * @param year + */ + private setYear(year: number) { + let date = this.displayDate; + this.displayDate = new Date(year, date.getMonth(), date.getDate(), date.getHours(), date.getMinutes()); + this.generateCalendar(); + this.isYearsVisible = false; + //this.isCalendarVisible = true; + } /** * Display Datepicker @@ -300,13 +358,18 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { /** * Display Calendar */ - private showCalendar() { this.isCalendarVisible = true; } + private showCalendar() { + this.isYearsVisible = false; + this.isCalendarVisible = true; + } /** * Toggle Hour visiblity */ private toggleHours(value: boolean) { + this.isYearsVisible = false; this.isCalendarVisible = false; + this.isYearsVisible = false; this.isHoursVisible = value; this._resetClock(); } @@ -315,7 +378,11 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { * Ok Button Event */ private onClickOk() { - if (this.isCalendarVisible) { + if (this.isYearsVisible) { + this.generateCalendar(); + this.isYearsVisible = false; + this.isCalendarVisible = true; + } else if (this.isCalendarVisible) { this.setDate(this.displayDate); } else if (this.isHoursVisible) { this.isHoursVisible = false; From 1422e93ddfc37f02a655d4ea9a8ae3d00b4572ff Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Thu, 6 Oct 2016 18:08:49 +0530 Subject: [PATCH 7/8] fix(autocomplete, datepicker, multiselect, select, tags) initial binding conflict --- src/lib/autocomplete/autocomplete.ts | 12 +++++++++--- src/lib/datepicker/datepicker.ts | 11 ++++++++--- src/lib/multiselect/multiselect.ts | 24 +++++++++++++++++------- src/lib/select/select.ts | 10 ++++++++-- src/lib/tags/tags.ts | 12 +++++++++--- 5 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/lib/autocomplete/autocomplete.ts b/src/lib/autocomplete/autocomplete.ts index 9bd298f36..d4e89f6c0 100644 --- a/src/lib/autocomplete/autocomplete.ts +++ b/src/lib/autocomplete/autocomplete.ts @@ -1,4 +1,5 @@ import { + AfterContentInit, Component, ElementRef, EventEmitter, @@ -93,14 +94,17 @@ export const MD2_AUTOCOMPLETE_CONTROL_VALUE_ACCESSOR: any = { encapsulation: ViewEncapsulation.None }) -export class Md2Autocomplete implements ControlValueAccessor { +export class Md2Autocomplete implements AfterContentInit, ControlValueAccessor { constructor(private element: ElementRef) { } + ngAfterContentInit() { this._isInitialized = true; } + @Output() change: EventEmitter = new EventEmitter(); private _value: any = ''; private _disabled: boolean = false; + private _isInitialized: boolean = false; private _onTouchedCallback: () => void = noop; private _onChangeCallback: (_: any) => void = noop; @@ -148,8 +152,10 @@ export class Md2Autocomplete implements ControlValueAccessor { if (this.selectedItem) { this.inputBuffer = this.selectedItem.text; } } if (!this.inputBuffer) { this.inputBuffer = ''; } - this._onChangeCallback(value); - this.change.emit(this._value); + if (this._isInitialized) { + this._onChangeCallback(value); + this.change.emit(this._value); + } } } diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index b6bc8e58d..30f2844c2 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -85,6 +85,7 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { } ngAfterContentInit() { + this._isInitialized = true; this.isCalendarVisible = this.type !== 'time' ? true : false; } @@ -92,6 +93,7 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { //private mouseUpListener: any; private _value: Date = null; + private _isInitialized: boolean = false; private _onTouchedCallback: () => void = noop; private _onChangeCallback: (_: any) => void = noop; @@ -153,8 +155,9 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { this.getYears(); } + @Input() get value(): any { return this._value; } - @Input() set value(value: any) { + set value(value: any) { if (value && value !== this._value) { if (this.dateUtil.isValidDate(value)) { this._value = value; @@ -177,8 +180,10 @@ export class Md2Datepicker implements AfterContentInit, ControlValueAccessor { if (this.type !== 'date') { date += this._value.getHours() + ':' + this._value.getMinutes(); } - this._onChangeCallback(date); - this.change.emit(date); + if (this._isInitialized) { + this._onChangeCallback(date); + this.change.emit(date); + } } } diff --git a/src/lib/multiselect/multiselect.ts b/src/lib/multiselect/multiselect.ts index effaf6a6a..d7b6b974b 100644 --- a/src/lib/multiselect/multiselect.ts +++ b/src/lib/multiselect/multiselect.ts @@ -1,4 +1,5 @@ import { + AfterContentInit, Component, ElementRef, EventEmitter, @@ -16,7 +17,7 @@ import { ControlValueAccessor, FormsModule, } from '@angular/forms'; -import {CommonModule} from '@angular/common'; +import { CommonModule } from '@angular/common'; class Option { public text: string; @@ -100,14 +101,17 @@ export const MD2_MULTISELECT_CONTROL_VALUE_ACCESSOR: any = { encapsulation: ViewEncapsulation.None }) -export class Md2Multiselect implements ControlValueAccessor { +export class Md2Multiselect implements AfterContentInit, ControlValueAccessor { constructor(private element: ElementRef) { } + ngAfterContentInit() { this._isInitialized = true; } + @Output() change: EventEmitter = new EventEmitter(); private _value: any = ''; private _disabled: boolean = false; + private _isInitialized: boolean = false; private _onTouchedCallback: () => void = noop; private _onChangeCallback: (_: any) => void = noop; @@ -119,7 +123,8 @@ export class Md2Multiselect implements ControlValueAccessor { private isFocused: boolean = false; @Input() id: string = 'md2-multiselect-' + (++nextId); - @Input() get disabled(): boolean { return this._disabled; } + @Input() + get disabled(): boolean { return this._disabled; } set disabled(value) { this._disabled = (value !== null && value !== false) ? true : null; } @@ -128,13 +133,16 @@ export class Md2Multiselect implements ControlValueAccessor { @Input('item-text') textKey: string = 'text'; @Input('item-value') valueKey: string = null; - @Input('items') set options(value: Array) { + @Input('items') + set options(value: Array) { this._options = value; } + + @Input() get value(): any { return this._value; } - @Input() set value(value: any) { + set value(value: any) { this.setValue(value); } @@ -152,8 +160,10 @@ export class Md2Multiselect implements ControlValueAccessor { if (selItm) { this.items.push(new Option(selItm, this.textKey, this.valueKey)); } } } - this._onChangeCallback(value); - this.change.emit(this._value); + if (this._isInitialized) { + this._onChangeCallback(value); + this.change.emit(this._value); + } } } diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts index a25065343..153c22c5d 100644 --- a/src/lib/select/select.ts +++ b/src/lib/select/select.ts @@ -1,4 +1,5 @@ import { + AfterContentInit, Injectable, AfterContentChecked, Component, @@ -96,12 +97,13 @@ export class Md2OptionChange { }, encapsulation: ViewEncapsulation.None }) -export class Md2Select implements AfterContentChecked, ControlValueAccessor { +export class Md2Select implements AfterContentInit, AfterContentChecked, ControlValueAccessor { private _value: any = null; private _name: string = 'md2-select-' + _uniqueIdCounter++; private _disabled: boolean = false; private _selected: Md2Option = null; + private _isInitialized: boolean = false; private isOpenable: boolean = true; private isMenuVisible: boolean = false; @@ -137,7 +139,9 @@ export class Md2Select implements AfterContentChecked, ControlValueAccessor { if (this._value !== newValue) { this._value = newValue; this._updateSelectedOptionValue(); - this._emitChangeEvent(); + if (this._isInitialized) { + this._emitChangeEvent(); + } } } @@ -153,6 +157,8 @@ export class Md2Select implements AfterContentChecked, ControlValueAccessor { constructor(public element: ElementRef) { } + ngAfterContentInit() { this._isInitialized = true; } + ngAfterContentChecked() { let opt = this._options.filter(o => this.equals(o.value, this.value))[0]; if (opt && !this.equals(this.selected, opt)) { diff --git a/src/lib/tags/tags.ts b/src/lib/tags/tags.ts index 4fd10424e..318af7d6d 100644 --- a/src/lib/tags/tags.ts +++ b/src/lib/tags/tags.ts @@ -1,4 +1,5 @@ import { + AfterContentInit, Component, ElementRef, EventEmitter, @@ -100,14 +101,17 @@ export const MD2_TAGS_CONTROL_VALUE_ACCESSOR: any = { encapsulation: ViewEncapsulation.None }) -export class Md2Tags implements ControlValueAccessor { +export class Md2Tags implements AfterContentInit, ControlValueAccessor { constructor(private element: ElementRef) { } + ngAfterContentInit() { this._isInitialized = true; } + @Output() change: EventEmitter = new EventEmitter(); private _value: any = ''; private _disabled: boolean = false; + private _isInitialized: boolean = false; private _onTouchedCallback: () => void = noop; private _onChangeCallback: (_: any) => void = noop; @@ -156,8 +160,10 @@ export class Md2Tags implements ControlValueAccessor { if (selItm) { this.items.push(new Tag(selItm, this.textKey, this.valueKey)); } } } - this._onChangeCallback(value); - this.change.emit(this._value); + if (this._isInitialized) { + this._onChangeCallback(value); + this.change.emit(this._value); + } } } From 2980c70e406e9389e8cb925ee3c7b2be8959b6ea Mon Sep 17 00:00:00 2001 From: dharmeshpipariya Date: Fri, 7 Oct 2016 10:11:45 +0530 Subject: [PATCH 8/8] published md@0.0.3 --- package.json | 2 +- src/lib/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 0d84de6bf..2f4ede53f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "md2", - "version": "0.0.2", + "version": "0.0.3", "description": "Angular2 based Material Design components, directives and services are Accordion, Autocomplete, Collapse, Colorpicker, Datepicker, Dialog(Modal), Menu, Multiselect, Select, Tabs, Tags(Chips), Toast and Tooltip.", "homepage": "https://github.com/Promact/md2", "bugs": "https://github.com/Promact/md2/issues", diff --git a/src/lib/package.json b/src/lib/package.json index b35b84fb8..bada6ff8a 100644 --- a/src/lib/package.json +++ b/src/lib/package.json @@ -1,6 +1,6 @@ { "name": "md2", - "version": "0.0.2", + "version": "0.0.3", "description": "Angular2 based Material Design components, directives and services are Accordion, Autocomplete, Collapse, Colorpicker, Datepicker, Dialog(Modal), Menu, Multiselect, Select, Tabs, Tags(Chips), Toast and Tooltip.", "homepage": "https://github.com/Promact/md2", "bugs": "https://github.com/Promact/md2/issues",