Skip to content

Commit

Permalink
Timepicker toggle button
Browse files Browse the repository at this point in the history
* feat(ngx-material-timepicker-toggle): add a button to open the timepicker

* ref(timepicker directive): set default time only after first value check

* ref(timepicker directive): make function more readable
  • Loading branch information
Agranom authored Jul 25, 2018
1 parent 0839820 commit f4b65c9
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ export class NgxMaterialTimepickerMinutesFaceComponent implements OnChanges {
@Input() period: TimePeriod;
@Input() minTime: Moment;
@Input() maxTime: Moment;

@Input()
set selectedHour(value: number) {
this._selectedHour = value === 12 ? 0 : value;
}

private _selectedHour: number;

@Output() minuteChange = new EventEmitter<ClockFaceTime>();

constructor() {
Expand All @@ -32,13 +40,6 @@ export class NgxMaterialTimepickerMinutesFaceComponent implements OnChanges {
});
}

private _selectedHour: number;

@Input()
set selectedHour(value: number) {
this._selectedHour = value === 12 ? 0 : value;
}

private get disabledMinutes(): ClockFaceTime[] {
if (this.minTime || this.maxTime) {

Expand All @@ -57,7 +58,7 @@ export class NgxMaterialTimepickerMinutesFaceComponent implements OnChanges {
}

ngOnChanges(changes: SimpleChanges) {
if (changes['period'] && changes['period']) {
if (changes['period'] && changes['period'].currentValue) {
this.minutesList = this.disabledMinutes;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<button class="ngx-material-timepicker-toggle" (click)="open($event)" [disabled]="disabled" type="button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px" *ngIf="!customIcon">
<path
d="M 12 2 C 6.4889971 2 2 6.4889971 2 12 C 2 17.511003 6.4889971 22 12 22 C 17.511003 22 22 17.511003 22 12 C 22 6.4889971 17.511003 2 12 2 z M 12 4 C 16.430123 4 20 7.5698774 20 12 C 20 16.430123 16.430123 20 12 20 C 7.5698774 20 4 16.430123 4 12 C 4 7.5698774 7.5698774 4 12 4 z M 11 6 L 11 12.414062 L 15.292969 16.707031 L 16.707031 15.292969 L 13 11.585938 L 13 6 L 11 6 z"/>
</svg>

<ng-content select="[ngxMaterialTimepickerToggleIcon]"></ng-content>
</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.ngx-material-timepicker-toggle {
display: flex;
justify-content: center;
align-items: center;
padding: 4px;
background-color: transparent;
border-radius: 50%;
text-align: center;
border: none;
outline: none;
user-select: none;
transition: background-color .3s;
cursor: pointer;
&:focus {
background-color: rgba(0, 0, 0, .07);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {Component, ContentChild, Input} from '@angular/core';
import {NgxMaterialTimepickerToggleIconDirective} from '../../directives/ngx-material-timepicker-toggle-icon.directive';
import {NgxMaterialTimepickerComponent} from '../../ngx-material-timepicker.component';

@Component({
selector: 'ngx-material-timepicker-toggle',
templateUrl: 'ngx-material-timepicker-toggle.component.html',
styleUrls: ['ngx-material-timepicker-toggle.component.scss']
})

export class NgxMaterialTimepickerToggleComponent {

@Input('for') timepicker: NgxMaterialTimepickerComponent;

@Input()
get disabled(): boolean {
return this._disabled === undefined ? this.timepicker.disabled : this._disabled;
}

set disabled(value: boolean) {
this._disabled = value;
}

private _disabled: boolean;

@ContentChild(NgxMaterialTimepickerToggleIconDirective) customIcon: NgxMaterialTimepickerToggleIconDirective;

open(event): void {
if (this.timepicker) {
this.timepicker.open();
event.stopPropagation();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {Directive} from '@angular/core';

//To override a default toggle icon
@Directive({selector: '[ngxMaterialTimepickerToggleIcon]'})

export class NgxMaterialTimepickerToggleIconDirective {
}
55 changes: 34 additions & 21 deletions src/app/material-timepicker/directives/ngx-timepicker.directive.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import {Directive, ElementRef, forwardRef, HostListener, Input, OnDestroy} from '@angular/core';
import {
Directive, ElementRef, forwardRef, HostListener, Input, OnChanges, OnDestroy,
SimpleChanges
} from '@angular/core';
import {NgxMaterialTimepickerComponent} from '../ngx-material-timepicker.component';
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
import {Subscription} from 'rxjs';
Expand All @@ -23,9 +26,10 @@ const VALUE_ACCESSOR = {
'(blur)': 'onTouched()',
}
})
export class TimepickerDirective implements ControlValueAccessor, OnDestroy {
export class TimepickerDirective implements ControlValueAccessor, OnDestroy, OnChanges {

@Input() disabled: boolean;
@Input() disableClick: boolean;

@Input('ngxTimepicker')
set timepicker(picker: NgxMaterialTimepickerComponent) {
Expand Down Expand Up @@ -75,22 +79,10 @@ export class TimepickerDirective implements ControlValueAccessor, OnDestroy {
set value(value: string) {
this._value = formatTime(value, this._format);

if (this._min && convertTimeToMoment(this._value).isAfter(this._min)) {
this.updateValue(value);
if (this.isValueAvailableToUpdate()) {
this.updateValue();
return;
}
if (this._max && convertTimeToMoment(this._value).isBefore(this._max)) {
this.updateValue(value);
return;
}
if ((this._min && this._max)
&& convertTimeToMoment(this._value).isBetween(this._min, this._max, 'minutes')) {
this.updateValue(value);
return;
}
if (!this._min && !this._max) {
this.updateValue(value);
}
console.warn('Selected time doesn\'t match min or max value');
}

Expand All @@ -115,9 +107,21 @@ export class TimepickerDirective implements ControlValueAccessor, OnDestroy {
this.onChange(value);
}

@HostListener('click')
onClick() {
this._timepicker.open();
ngOnChanges(changes: SimpleChanges) {
if (changes['value'] && changes['value'].firstChange) {
if (this.isValueAvailableToUpdate()) {
this.updateValue();
this._timepicker.setDefaultTime(this._value);
}
}
}

@HostListener('click', ['$event'])
onClick(event) {
if (!this.disableClick) {
this._timepicker.open();
event.stopPropagation();
}
}

writeValue(value: string): void {
Expand Down Expand Up @@ -152,9 +156,18 @@ export class TimepickerDirective implements ControlValueAccessor, OnDestroy {
}
}

private updateValue(value: string): void {
private updateValue(): void {
this.elementRef.nativeElement.value = this._value;
this._timepicker.setDefaultTime(formatTime(value));
}

private isValueAvailableToUpdate(): boolean {
const isAfter = this._min && convertTimeToMoment(this._value).isAfter(this._min);
const isBefore = this._max && convertTimeToMoment(this._value).isBefore(this._max);
const isBetween = (this._min && this._max)
&& convertTimeToMoment(this._value).isBetween(this._min, this._max, 'minutes');
const isAvailable = !this._min && !this._max;

return isAfter || isBefore || isBetween || isAvailable;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ export class NgxMaterialTimepickerComponent implements OnInit, OnDestroy {
return this.timepickerInput && this.timepickerInput.max;
}

get disabled(): boolean {
return this.timepickerInput && this.timepickerInput.disabled;
}

ngOnInit() {
this.subscriptions.push(this.timepickerService.selectedHour.pipe(
tap(hour => this.selectedHour = hour),
Expand Down Expand Up @@ -154,6 +158,7 @@ export class NgxMaterialTimepickerComponent implements OnInit, OnDestroy {
@HostListener('keydown', ['$event'])
onKeydown(e: KeyboardEvent) {
this.eventService.keydownEventSubject.next(e);
e.stopPropagation();
}

ngOnDestroy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,32 @@ import {TimepickerDirective} from './directives/ngx-timepicker.directive';
import {OverlayDirective} from './directives/overlay.directive';
import {NgxMaterialTimepickerEventService} from './services/ngx-material-timepicker-event.service';
import {FocusAnchorDirective} from './directives/focus-anchor.directive';
import {NgxMaterialTimepickerToggleComponent} from './components/timepicker-toggle-button/ngx-material-timepicker-toggle.component';
import {NgxMaterialTimepickerToggleIconDirective} from './directives/ngx-material-timepicker-toggle-icon.directive';

@NgModule({
imports: [
CommonModule
],
exports: [
NgxMaterialTimepickerComponent,
TimepickerDirective
NgxMaterialTimepickerToggleComponent,
TimepickerDirective,
NgxMaterialTimepickerToggleIconDirective
],
declarations: [
NgxMaterialTimepickerComponent,
StyleSanitizerPipe,
NgxMaterialTimepickerHoursFaceComponent,
NgxMaterialTimepickerMinutesFaceComponent,
NgxMaterialTimepickerFaceComponent,
NgxMaterialTimepickerToggleComponent,
TimeFormatterPipe,
NgxMaterialTimepickerButtonComponent,
TimepickerDirective,
OverlayDirective,
FocusAnchorDirective,
NgxMaterialTimepickerToggleIconDirective
]
})
export class NgxMaterialTimepickerModule {
Expand Down

0 comments on commit f4b65c9

Please sign in to comment.