Skip to content

Instantly share code, notes, and snippets.

@vespertilian
Created September 15, 2016 10:12
Show Gist options
  • Save vespertilian/dd4283442622e5c36fa6f9526059a515 to your computer and use it in GitHub Desktop.
Save vespertilian/dd4283442622e5c36fa6f9526059a515 to your computer and use it in GitHub Desktop.
Date filter in Angular 1.2 using angular 2 style inputs (one way) and outputs (events).
let templateUrl: string = require('./date-filter.jade');
require('./date-filters.sass');
// note: to call the on change values you must match this call signature
// on-validation-change='vm.validationChange(valid)',
// on-date-change='vm.dateChange({toDate: toDate, fromDate: fromDate})',
export function dateFilter(): ng.IDirective {
return {
restrict: 'A',
scope: {
inputFromDate: '=',
inputToDate: '=',
onDateChange: '&',
onValidationChange: '&',
},
templateUrl: templateUrl,
controller: DateFilterController,
controllerAs: 'vm',
bindToController: true,
};
}
export interface IDateParams {
fromDate: string;
toDate: string;
}
export interface IValidParams {
valid: boolean;
}
export interface IDateFilterScope extends ng.IScope {
inputFromDate: any;
inputToDate: any;
onValidationChange: (validParams: IValidParams) => void;
onDateChange: (dateParams: IDateParams) => void;
}
export class DateFilterController {
public toDateModel: Date;
public fromDateModel: Date;
public today: Date;
public dateOptions: any;
public format: string;
public toDateOpen: boolean;
public fromDateOpen: boolean;
public fromDateGreaterThanToDate: boolean;
public toDateInFuture: boolean;
public periodGreaterThanOneMonth: boolean;
// ie8 being used in view
/*@ngInject*/
constructor(
private moment: any,
private $scope: IDateFilterScope,
public ie8: boolean
) {
this.format = 'dd/MM/yy';
this.today = new Date();
this.dateOptions = {
formatYear: 'yy',
startingDay: 1,
};
// by copying the value we create a one way binding
$scope.$watch('inputFromDate', (newValue: string) => {
if (newValue) {
this.fromDateModel = angular.copy(moment(newValue, 'YYYYMMDD')._d);
this.validate();
}
});
// by copying the value we create a one way binding
$scope.$watch('inputToDate', (newValue: string) => {
if (newValue) {
this.toDateModel = angular.copy(moment(newValue, 'YYYYMMDD')._d);
this.validate();
}
});
}
public open($event: ng.IAngularEvent, openDatePicker: string): void {
$event.preventDefault();
$event.stopPropagation();
this[openDatePicker] = true;
}
public dateChanged(): void {
// called via ng-change
let toDateString: string = this.moment(this.toDateModel).format('YYYYMMDD');
let fromDateString: string = this.moment(this.fromDateModel).format('YYYYMMDD');
if (this.$scope.onDateChange) {
this.$scope.onDateChange({fromDate: fromDateString, toDate: toDateString});
}
this.validate();
}
private validate(): void {
let fromDate: any = this.moment(this.fromDateModel);
let toDate: any = this.moment(this.toDateModel);
let now: any = this.moment();
this.fromDateGreaterThanToDate = fromDate.diff(toDate) > 0;
this.toDateInFuture = toDate.diff(now) > 0;
this.periodGreaterThanOneMonth = toDate.diff(fromDate, 'months', true) > 1;
let valid: boolean = !this.fromDateGreaterThanToDate && !this.toDateInFuture && !this.periodGreaterThanOneMonth;
if (this.$scope.onValidationChange) {
this.$scope.onValidationChange({valid: valid});
}
}
}
.row
.col-md-12
div(ng-click='vm.toggleCalendar()')
form.row(ng-submit='vm.changeDate()')
label.col-md-12
| Date range
.field.col-md-6
input#plainFromDateInput(
ng-if='vm.ie8',
ng-model='vm.fromDateModel',
date-input-formatter,
ng-change='vm.dateChanged()'
)
p.input-group(ng-if='!vm.ie8')
input.form-control.date-filter-from-date(type='text', datepicker-popup='{{vm.format}}', ng-model='vm.fromDateModel', is-open='vm.fromDateOpen', max-date='vm.today', datepicker-options='vm.dateOptions', ng-required='true', close-text='Close', ng-change='vm.dateChanged()')
span.input-group-btn
button.btn.btn-default.date-filter-button(type='button', ng-click="vm.open($event, 'fromDateOpen')")
i.glyphicon.glyphicon-calendar
span.date-range-text
| to
.field.col-md-6
input#plainToDateInput(
ng-if='vm.ie8',
ng-model='vm.toDateModel',
date-input-formatter,
ng-change='vm.dateChanged()'
)
p.input-group(ng-if='!vm.ie8')
input.form-control.date-filter-to-date(type='text', datepicker-popup='{{vm.format}}', ng-model='vm.toDateModel', is-open='vm.toDateOpen', max-date='vm.today', datepicker-options='vm.dateOptions', ng-required='true', close-text='Close', ng-change='vm.dateChanged()')
span.input-group-btn
button.btn.btn-default.date-filter-button(type='button', ng-click="vm.open($event, 'toDateOpen')")
i.glyphicon.glyphicon-calendar
.alert.alert-warning(ng-if='vm.toDateInFuture')
| To date cannot be in the future.
.alert.alert-warning(ng-if='vm.fromDateGreaterThanToDate')
| The from date should be before the to date.
.alert.alert-warning(ng-if='vm.periodGreaterThanOneMonth')
| The date range period must be one month or less.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment