From 389b251c577e9057b84b79036e2afc8ce65530a2 Mon Sep 17 00:00:00 2001 From: sashaqred Date: Tue, 25 Oct 2022 21:02:50 +0400 Subject: [PATCH] feat: add initial min max validation --- .../timepicker/timepicker.component.ts | 14 +++++ .../timepicker/timepicker.directive.ts | 53 ++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/framework/theme/components/timepicker/timepicker.component.ts b/src/framework/theme/components/timepicker/timepicker.component.ts index 947c522295..c1da1b9738 100644 --- a/src/framework/theme/components/timepicker/timepicker.component.ts +++ b/src/framework/theme/components/timepicker/timepicker.component.ts @@ -161,6 +161,16 @@ export class NbTimePickerComponent implements OnChanges { _date: D; + /** + * Minimum available date for selection. + * */ + @Input() min: D; + + /** + * Maximum available date for selection. + * */ + @Input() max: D; + /** * In timepicker value should be always true * In calendar-with-time.component should set to false @@ -320,6 +330,10 @@ export class NbTimePickerComponent implements OnChanges { return false; } + getValidatorConfig() { + return { min: this.min, max: this.max }; + } + protected buildColumnOptions(): void { this.fullTimeOptions = this.singleColumn ? this.calendarTimeModelService.getHoursRange(this.step) : []; diff --git a/src/framework/theme/components/timepicker/timepicker.directive.ts b/src/framework/theme/components/timepicker/timepicker.directive.ts index 5a292b3902..8bb285d412 100644 --- a/src/framework/theme/components/timepicker/timepicker.directive.ts +++ b/src/framework/theme/components/timepicker/timepicker.directive.ts @@ -13,7 +13,15 @@ import { } from '@angular/core'; import { distinctUntilChanged, filter, map, pairwise, startWith, takeUntil } from 'rxjs/operators'; import { fromEvent, merge, Subject, Subscription } from 'rxjs'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { + ControlValueAccessor, + NG_VALIDATORS, + NG_VALUE_ACCESSOR, + ValidationErrors, + Validator, + ValidatorFn, + Validators, +} from '@angular/forms'; import { NbTimePickerComponent } from './timepicker.component'; import { NbOverlayRef, NbScrollStrategy } from '../cdk/overlay/mapping'; import { @@ -176,9 +184,14 @@ import { NB_DOCUMENT } from '../../theme.options'; useExisting: forwardRef(() => NbTimePickerDirective), multi: true, }, + { + provide: NG_VALIDATORS, + useExisting: forwardRef(() => NbTimePickerDirective), + multi: true, + }, ], }) -export class NbTimePickerDirective implements AfterViewInit, ControlValueAccessor { +export class NbTimePickerDirective implements AfterViewInit, ControlValueAccessor, Validator { /** * Provides timepicker component. * */ @@ -260,6 +273,13 @@ export class NbTimePickerDirective implements AfterViewInit, ControlValueAcce return !this.isOpen; } + /** + * Form control validators will be called in validators context, so, we need to bind them. + * */ + protected validator: ValidatorFn = Validators.compose( + [this.minValidator, this.maxValidator].map((fn) => fn.bind(this)), + ); + constructor( @Inject(NB_DOCUMENT) protected document, protected positionBuilder: NbPositionBuilderService, @@ -465,6 +485,13 @@ export class NbTimePickerDirective implements AfterViewInit, ControlValueAcce this.onTouched = fn; } + /** + * Form control validation based on picker validator config. + * */ + validate(): ValidationErrors | null { + return this.validator(null); + } + protected parseNativeDateString(value: string): string { const date = this.dateService.today(); const year = this.dateService.getYear(date); @@ -473,4 +500,26 @@ export class NbTimePickerDirective implements AfterViewInit, ControlValueAcce return `${year}-${month}-${day} ${value}`; } + + /** + * Validates passed value is greater than min. + * */ + protected minValidator(): ValidationErrors | null { + const config = this.timepicker.getValidatorConfig(); + const date = this.dateService.parse(this.inputValue, this.timepicker.computedTimeFormat); + return !config.min || !date || this.dateService.compareDates(config.min, date) <= 0 + ? null + : { nbDatepickerMin: { min: config.min, actual: date } }; + } + + /** + * Validates passed value is smaller than max. + * */ + protected maxValidator(): ValidationErrors | null { + const config = this.timepicker.getValidatorConfig(); + const date = this.dateService.parse(this.inputValue, this.timepicker.computedTimeFormat); + return !config.max || !date || this.dateService.compareDates(config.max, date) >= 0 + ? null + : { nbDatepickerMax: { max: config.max, actual: date } }; + } }