Skip to content

Commit

Permalink
feat(datepicker): added date and range min, max and invalid validation (
Browse files Browse the repository at this point in the history
#3499)

closes #2727
closes #3498
  • Loading branch information
valorkin authored Jan 19, 2018
1 parent 7c53bf9 commit 7b43295
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
<div class="row">
<div class="col-xs-12 col-12 col-sm-6 col-md-4 form-group">
<input class="form-control" placeholder="Datepicker" bsDatepicker [minDate]="minDate" [maxDate]="maxDate" #dp="bsDatepicker">
<input class="form-control"
placeholder="Datepicker"
ngModel
bsDatepicker
[minDate]="minDate"
[maxDate]="maxDate">
</div>
<div class="col-xs-12 col-12 col-sm-6 col-md-4 form-group">
<input class="form-control" placeholder="Daterangepicker" bsDaterangepicker [minDate]="minDate" [maxDate]="maxDate" #dpr="bsDaterangepicker">
<input class="form-control"
placeholder="Daterangepicker"
ngModel
bsDaterangepicker
[minDate]="minDate"
[maxDate]="maxDate">
</div>
</div>

Expand Down
51 changes: 45 additions & 6 deletions src/datepicker/bs-datepicker-input.directive.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { ChangeDetectorRef, Directive, ElementRef, forwardRef, Host, Renderer2 } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { BsDatepickerDirective } from './bs-datepicker.component';
import {
AbstractControl, ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors,
Validator
} from '@angular/forms';
import { parseDate } from '../chronos/create/local';
import { formatDate } from '../chronos/format';
import { getLocale } from '../chronos/locale/locales';
import { BsLocaleService } from './bs-locale.service';
import { isAfter, isBefore } from '../chronos/utils/date-compare';
import { isDate, isDateValid } from '../chronos/utils/type-checks';
import { BsDatepickerDirective } from './bs-datepicker.component';
import { BsDatepickerConfig } from './bs-datepicker.config';
import { parseDate } from '../chronos/create/local';
import { BsLocaleService } from './bs-locale.service';

const BS_DATEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
Expand All @@ -14,19 +19,26 @@ const BS_DATEPICKER_VALUE_ACCESSOR = {
multi: true
};

const BS_DATEPICKER_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => BsDatepickerInputDirective),
multi: true
};

@Directive({
selector: `input[bsDatepicker]`,
host: {
'(change)': 'onChange($event)',
'(keyup.esc)': 'hide()',
'(blur)': 'onBlur()'
},
providers: [BS_DATEPICKER_VALUE_ACCESSOR]
providers: [BS_DATEPICKER_VALUE_ACCESSOR, BS_DATEPICKER_VALIDATOR]
})
export class BsDatepickerInputDirective
implements ControlValueAccessor {
implements ControlValueAccessor, Validator {
private _onChange = Function.prototype;
private _onTouched = Function.prototype;
private _validatorChange = Function.prototype;
private _value: Date;

constructor(@Host() private _picker: BsDatepickerDirective,
Expand Down Expand Up @@ -65,6 +77,33 @@ export class BsDatepickerInputDirective
this._onTouched();
}

validate(c: AbstractControl): ValidationErrors | null {
const _value: Date | string = c.value;

if (_value === null || _value === undefined || _value === '') {
return null;
}

if (isDate(_value)) {
const _isDateValid = isDateValid(_value);
if (!_isDateValid) {
return { bsDate: { invalid: _value } };
}

if (this._picker && this._picker.minDate && isBefore(_value, this._picker.minDate, 'date')) {
return { bsDate: { minDate: this._picker.minDate } };
}

if (this._picker && this._picker.maxDate && isAfter(_value, this._picker.maxDate, 'date')) {
return { bsDate: { maxDate: this._picker.maxDate } };
}
}
}

registerOnValidatorChange(fn: () => void): void {
this._validatorChange = fn;
}

writeValue(value: Date | string) {
if (!value) {
this._value = null;
Expand Down
53 changes: 47 additions & 6 deletions src/datepicker/bs-daterangepicker-input.directive.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { ChangeDetectorRef, Directive, ElementRef, forwardRef, Host, OnInit, Renderer2 } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { ChangeDetectorRef, Directive, ElementRef, forwardRef, Host, Renderer2 } from '@angular/core';
import {
AbstractControl, ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors,
Validator
} from '@angular/forms';
import { parseDate } from '../chronos/create/local';
import { formatDate } from '../chronos/format';
import { getLocale } from '../chronos/locale/locales';
import { isAfter, isBefore } from '../chronos/utils/date-compare';
import { isArray, isDateValid } from '../chronos/utils/type-checks';
import { BsDatepickerConfig } from './bs-datepicker.config';
import { BsDaterangepickerDirective } from './bs-daterangepicker.component';
import { BsLocaleService } from './bs-locale.service';
import { BsDatepickerConfig } from './bs-datepicker.config';
import { parseDate } from '../chronos/create/local';

const BS_DATERANGEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
Expand All @@ -14,19 +19,28 @@ const BS_DATERANGEPICKER_VALUE_ACCESSOR = {
multi: true
};


const BS_DATERANGEPICKER_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => BsDaterangepickerInputDirective),
multi: true
};


@Directive({
selector: `input[bsDaterangepicker]`,
host: {
'(change)': 'onChange($event)',
'(keyup.esc)': 'hide()',
'(blur)': 'onBlur()'
},
providers: [BS_DATERANGEPICKER_VALUE_ACCESSOR]
providers: [BS_DATERANGEPICKER_VALUE_ACCESSOR, BS_DATERANGEPICKER_VALIDATOR]
})
export class BsDaterangepickerInputDirective
implements ControlValueAccessor {
implements ControlValueAccessor, Validator {
private _onChange = Function.prototype;
private _onTouched = Function.prototype;
private _validatorChange = Function.prototype;
private _value: Date[];

constructor(@Host() private _picker: BsDaterangepickerDirective,
Expand Down Expand Up @@ -77,6 +91,33 @@ export class BsDaterangepickerInputDirective
this._onTouched();
}

validate(c: AbstractControl): ValidationErrors | null {
const _value: [Date, Date] = c.value;

if (_value === null || _value === undefined || !isArray(_value)) {
return null;
}


const _isDateValid = isDateValid(_value[0]) && isDateValid(_value[0]);

if (!_isDateValid) {
return { bsDate: { invalid: _value } };
}

if (this._picker && this._picker.minDate && isBefore(_value[0], this._picker.minDate, 'date')) {
return { bsDate: { minDate: this._picker.minDate } };
}

if (this._picker && this._picker.maxDate && isAfter(_value[1], this._picker.maxDate, 'date')) {
return { bsDate: { maxDate: this._picker.maxDate } };
}
}

registerOnValidatorChange(fn: () => void): void {
this._validatorChange = fn;
}

writeValue(value: Date[] | string) {
if (!value) {
this._value = null;
Expand Down

0 comments on commit 7b43295

Please sign in to comment.