Skip to content

Commit 2981ac2

Browse files
committed
Last changes to upgrade to 2.0 bootstrap daterangepicker
1 parent 16fdd99 commit 2981ac2

File tree

3 files changed

+108
-61
lines changed

3 files changed

+108
-61
lines changed

bower.json

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
],
2121
"dependencies": {
2222
"angular": "^1.2.17",
23+
"angular-messages": "^1.2.17",
2324
"bootstrap": "^3.0.0",
2425
"bootstrap-daterangepicker": "^2.0.0"
2526
},

coffee/angular-daterangepicker.coffee

+75-48
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ picker.directive 'dateRangePicker', ($compile, $timeout, $parse, dateRangePicker
1313
scope:
1414
min: '='
1515
max: '='
16-
model: '=ngmodel'
16+
model: '=ngModel'
1717
opts: '=options'
1818
clearable: '='
1919
link: ($scope, element, attrs, modelCtrl) ->
@@ -22,16 +22,14 @@ picker.directive 'dateRangePicker', ($compile, $timeout, $parse, dateRangePicker
2222
opts = angular.merge({}, dateRangePickerConfig, customOpts)
2323
_picker = null
2424

25-
clear = ->
25+
_clear = ->
2626
_picker.setStartDate()
2727
_picker.setEndDate()
2828

2929
_setDatePoint = (setter) ->
3030
(newValue) ->
31-
if (_picker)
32-
if not newValue
33-
then clear()
34-
else setter(moment(newValue))
31+
if _picker and newValue
32+
setter(moment(newValue))
3533

3634
_setStartDate = _setDatePoint (m) ->
3735
if (_picker.endDate < m)
@@ -43,27 +41,27 @@ picker.directive 'dateRangePicker', ($compile, $timeout, $parse, dateRangePicker
4341
_picker.setStartDate(m)
4442
_picker.setEndDate(m)
4543

46-
#Watchers enable resetting of start and end dates
47-
$scope.$watch 'model.startDate', _setStartDate
48-
$scope.$watch 'model.endDate', _setEndDate
49-
50-
_format = (viewVal) ->
44+
# Formats the obj into the string for the element input
45+
_format = (objValue) ->
5146
f = (date) ->
5247
if not moment.isMoment(date)
5348
then moment(date).format(opts.locale.format)
5449
else date.format(opts.locale.format)
5550

56-
if opts.singleDatePicker
57-
then f(viewVal.startDate)
58-
else [f(viewVal.startDate), f(viewVal.endDate)].join(opts.locale.separator)
51+
if objValue and objValue.startDate
52+
if opts.singleDatePicker
53+
then f(objValue.startDate)
54+
else [f(objValue.startDate), f(objValue.endDate)].join(opts.locale.separator)
55+
else ''
5956

60-
_parse = (value) ->
61-
f = (val) ->
62-
moment(val, opts.locale.format)
63-
if opts.singleDatePicker
64-
then f(value)
65-
else value.split(opts.locale.separator).map(f)
57+
# Sets the viewValue as well as updating the input element's value
58+
# Note: This is necessary as we don't allow the date picker to update the text (using autoUpdateInput: false)
59+
_setViewValue = (objValue) ->
60+
value = _format(objValue)
61+
el.val(value)
62+
modelCtrl.$setViewValue(value)
6663

64+
# Validation for our min/max
6765
_validate = (validator) ->
6866
(boundary, actual) ->
6967
if boundary and actual
@@ -73,57 +71,74 @@ picker.directive 'dateRangePicker', ($compile, $timeout, $parse, dateRangePicker
7371
_validateMin = _validate (min, start) -> min.isBefore(start) or min.isSame(start, 'day')
7472
_validateMax = _validate (max, end) -> max.isAfter(end) or max.isSame(end, 'day')
7573

74+
# Formatter should return just the string value of the input
75+
# It is used for comparison of if we should re-render
7676
modelCtrl.$formatters.push (val) ->
7777
if val and val.startDate
7878
then _format(val)
7979
else ''
8080

81+
# Render should update the date picker start/end dates as necessary
82+
# It should also set the input element's val with $viewValue as we don't let the rangepicker do this
83+
modelCtrl.$render = () ->
84+
# Update the calendars
85+
if modelCtrl.$modelValue and modelCtrl.$modelValue.startDate
86+
_setStartDate(modelCtrl.$modelValue.startDate)
87+
_setEndDate(modelCtrl.$modelValue.endDate)
88+
else
89+
_clear()
90+
# Update the input
91+
el.val(modelCtrl.$viewValue)
92+
93+
# This should parse the string input into an updated model object
8194
modelCtrl.$parsers.push (val) ->
82-
# Check if input is valid.
83-
value =
95+
# Parse the string value
96+
f = (value) ->
97+
moment(value, opts.locale.format)
98+
objValue =
8499
startDate: null
85100
endDate: null
86101
if angular.isString(val) and val.length > 0
87-
x = _parse(val)
88-
value.startDate = x[0]
89-
value.endDate = x[1]
90-
value
102+
if opts.singleDatePicker
103+
objValue.startDate = f(val)
104+
else
105+
x = val.split(opts.locale.separator).map(f)
106+
objValue.startDate = x[0]
107+
objValue.endDate = x[1]
108+
objValue
91109

92110
modelCtrl.$isEmpty = (val) ->
93-
# modelCtrl is empty if val is invalid or any of the ranges are not set.
94-
not val or val.startDate == null or val.endDate == null
95-
96-
modelCtrl.$render = ->
97-
if modelCtrl.$modelValue and modelCtrl.$modelValue.startDate != null
98-
_setStartDate(modelCtrl.$modelValue.startDate)
99-
_setEndDate(modelCtrl.$modelValue.endDate)
100-
else
101-
clear()
111+
# modelCtrl is empty if val is empty string
112+
not val and val.length > 0
102113

114+
# _init has to be called anytime we make changes to the date picker options
103115
_init = ->
104-
el.daterangepicker opts
116+
# disable autoUpdateInput, can't handle empty values without it. Our callback here will
117+
# update our $viewValue, which triggers the $parsers
118+
el.daterangepicker angular.extend(opts, {autoUpdateInput: false}), (start, end) ->
119+
_setViewValue({startDate: start, endDate: end})
105120

106121
# Needs to be after daterangerpicker has been created, otherwise
107122
# watchers that reinit will be attached to old daterangepicker instance.
108123
_picker = el.data('daterangepicker')
109124

110-
#Ability to attach event handlers. See https://github.com/fragaria/angular-daterangepicker/pull/62
125+
# Ability to attach event handlers. See https://github.com/fragaria/angular-daterangepicker/pull/62
111126
for eventType, callbackFunction of opts.eventHandlers
112127
el.on eventType, () ->
113128
$scope.$evalAsync(callbackFunction)
114129

115-
if attrs.clearable
116-
locale = opts.locale || {}
117-
locale.cancelLabel = opts.clearLabel
118-
opts.locale = locale
119-
120-
el.on 'cancel.daterangepicker', () ->
121-
modelCtrl.$setViewValue({startDate: null, endDate: null})
122-
modelCtrl.$render()
123-
return el.trigger 'change'
124-
125130
_init()
126131

132+
# Watchers enable resetting of start and end dates
133+
# Update the date picker, and set a new viewValue of the model
134+
$scope.$watch 'model.startDate', (n) ->
135+
_setStartDate(n)
136+
_setViewValue($scope.model)
137+
$scope.$watch 'model.endDate', (n) ->
138+
_setEndDate(n)
139+
_setViewValue($scope.model)
140+
141+
# Add validation/watchers for our min/max fields
127142
_initBoundaryField = (field, validator, modelField, optName) ->
128143
if attrs[field]
129144
modelCtrl.$validators[field] = (value) ->
@@ -135,11 +150,23 @@ picker.directive 'dateRangePicker', ($compile, $timeout, $parse, dateRangePicker
135150
_initBoundaryField('min', _validateMin, 'startDate', 'minDate')
136151
_initBoundaryField('max', _validateMax, 'endDate', 'maxDate')
137152

153+
# Watch our options
138154
if attrs.options
139155
$scope.$watch 'opts', (newOpts) ->
140-
opts = angular.merge(opts, newOpts, {autoUpdateInput: false})
156+
opts = angular.merge(opts, newOpts)
141157
_init()
142158
, true
143159

160+
# Watch clearable flag
161+
if attrs.clearable
162+
$scope.$watch 'clearable', (newClearable) ->
163+
if newClearable
164+
opts = angular.merge(opts, {locale: {cancelLabel: opts.clearLabel}})
165+
_init()
166+
el.on 'cancel.daterangepicker', (
167+
if newClearable
168+
then _setViewValue.bind(this, {startDate: null, endDate: null})
169+
else null)
170+
144171
$scope.$on '$destroy', ->
145172
_picker?.remove()

example.html

+32-13
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<!-- bower:js -->
1717
<script src="lib/jquery/dist/jquery.js"></script>
1818
<script src="lib/angular/angular.js"></script>
19+
<script src="lib/angular-messages/angular-messages.js"></script>
1920
<script src="lib/bootstrap/dist/js/bootstrap.js"></script>
2021
<script src="lib/moment/moment.js"></script>
2122
<script src="lib/bootstrap-daterangepicker/daterangepicker.js"></script>
@@ -28,37 +29,44 @@ <h1>Daterange picker example</h1>
2829

2930
<div class="row">
3031
<div class="col-md-6" ng-controller="TestCtrl">
31-
<form class="form-horizontal">
32+
<form name="dateForm" class="form-horizontal">
3233
<div class="form-group">
3334
<label for="daterange1" class="control-label">Simple picker</label>
34-
<input date-range-picker id="daterange1" class="form-control date-picker" type="text"
35-
name="date" ng-model="date" required/>
35+
<input date-range-picker id="daterange1" name="daterange1" class="form-control date-picker" type="text"
36+
ng-model="date" required/>
3637
</div>
37-
<div class="form-group">
38+
<div class="form-group" ng-class="{'has-error': dateForm.daterange2.$invalid}">
3839
<label for="daterange2" class="control-label">Picker with min and max date</label>
39-
<input date-range-picker id="daterange2" class="form-control date-picker" type="text"
40-
min="'2014-02-23'" max="'2015-02-25'" name="date" ng-model="date"
40+
<input date-range-picker id="daterange2" name="daterange2" class="form-control date-picker" type="text"
41+
min="'2015-01-23'" max="'2015-08-25'" ng-model="date"
4142
required/>
43+
<div class="help-block" ng-messages="dateForm.daterange2.$error">
44+
<p ng-message="min">Start date is too far in the past.</p>
45+
<p ng-message="max">End date is too far in the future.</p>
46+
<p ng-message="required">Range is required.</p>
47+
</div>
4248
</div>
4349
<div class="form-group">
4450
<label for="daterange3" class="control-label">Picker with custom locale</label>
45-
<input date-range-picker id="daterange3" class="form-control date-picker" type="text"
46-
name="date" ng-model="date" options="opts" required/>
51+
<input date-range-picker id="daterange3" name="daterange3" class="form-control date-picker" type="text"
52+
ng-model="date" options="opts" required/>
4753
</div>
4854
<div class="form-group">
4955
<label for="daterange4" class="control-label">Clearable picker</label>
50-
<input date-range-picker id="daterange4" class="form-control date-picker" type="text"
51-
name="date" ng-model="date" clearable="true" required/>
56+
<input date-range-picker id="daterange4" name="daterange4" class="form-control date-picker" type="text"
57+
ng-model="date" clearable="true" required/>
5258
</div>
5359
<div class="form-group">
5460
<label for="daterange5" class="control-label">Picker with custom format</label>
5561
<div class="input-group col-md-6" id="daterange5">
5662
<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
57-
<input date-range-picker class="form-control date-picker" type="text"
58-
name="date2" ng-model="date2" options="{locale: {format: 'MMMM D, YYYY'}}" required/>
63+
<input date-range-picker name="daterange5" class="form-control date-picker" type="text"
64+
ng-model="date2" options="{locale: {format: 'MMMM D, YYYY'}}" required/>
5965
<span class="input-group-addon"><span class="glyphicon glyphicon-chevron-down"></span></span>
6066
</div>
6167
</div>
68+
<button type="button" class="btn" ng-click="setStartDate()">Set Start Date</button>
69+
<button type="button" class="btn" ng-click="setRange()">Set Range</button>
6270
</form>
6371

6472
<div class="row">
@@ -75,7 +83,7 @@ <h4>Dates:</h4>
7583

7684

7785
<script>
78-
exampleApp = angular.module('example', ['daterangepicker']);
86+
exampleApp = angular.module('example', ['ngMessages', 'daterangepicker']);
7987
exampleApp.controller('TestCtrl', function($scope) {
8088
$scope.date = {
8189
startDate: moment().subtract(1, "days"),
@@ -106,6 +114,17 @@ <h4>Dates:</h4>
106114
}
107115
};
108116

117+
$scope.setStartDate = function () {
118+
$scope.date.startDate = moment().subtract(4, "days");
119+
};
120+
121+
$scope.setRange = function () {
122+
$scope.date = {
123+
startDate: moment().subtract(5, "days"),
124+
endDate: moment()
125+
};
126+
};
127+
109128
//Watch for date changes
110129
$scope.$watch('date', function(newDate) {
111130
console.log('New date set: ', newDate);

0 commit comments

Comments
 (0)