I'm using Angular UI Bootstrap Datepicker: https://angular-ui.github.io/bootstrap/#/datepicker
When I render form using data received from the server, there is problem with datetime fields. My input datepicker looks like this:
<form name="itemForm">
<input type="datetime" class="form-control" id="startedAt" name="startedAt"
ng-model="item.startedAt"
ng-click="open($event, 'startedAt')"
uib-datepicker-popup="yyyy-MM-dd"
is-open="datepickers.startedAt"
/>
</form>
My server returns response datetime as JSON string:
{
...
startedAt: "2015-05-29T02:00:00+0200"
}
When I assign response data to the model $scope.item = response;
, datepicker input field is rendered correctly (correct date is selected and it's properly formatted in format I selected). The problem is that validation does not pass. I get:
itemForm.startedAt.$invalid == true
I noticed that data bound to the datepicker field should be Date
object and not string (when I select new date from the datepicker, $scope.item.startedAt
is a Date
)
I managed to work around this issue and do this in the controller:
$scope.item = response;
$scope.item.startedAt = new Date($scope.item.startedAt);
It works this way... But I wouldn't like to manually convert string do date every time I get a response from the server. I tried to create a directive, that I can assign to the datepicker input field so it converts the ng-model
for me:
.directive("asDate", function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, modelCtrl) {
modelCtrl.$formatters.push(function (input) {
var transformedInput = new Date(input);
if (transformedInput != input) {
modelCtrl.$setViewValue(transformedInput);
modelCtrl.$render();
}
return transformedInput;
});
}
}
})
Well it works, because now I can see Date
object, when I output model in my view: {{item.startedAt}}
. However still validation fails! I suspect this is some problem with me understanding how data flows between model and the view, and how UI Bootstrap hooks into it.
Also when I change my directive from $formatters.push
to $formatters.unshift
, validation works OK, but datepicker does not format my datetime (insted of nicely formattet yyyy-MM-dd
I see ISO string inside the input)
This broke as of Angular.UI.Bootstrap v0.13.2 (8-2-2015) Downgrading to 0.13.1 works, which is where I'm stuck today.
Wesleycho says this was done intentionally https://github.com/angular-ui/bootstrap/issues/4690
I'm ready for other date pickers that support strings if anyone has a suggestion
...soon after posting this I went down a non-angular path that I'm not proud of, but it works for both HTML5 type="date" and uib-datepicker-popup. I have a regular expression that determines if a string resembles one of the two serialized date formats I've seen, and then I have a recursive javascript function to traverse a json tree and replace those strings with Date(). You would call it just before you put in $scope (or viewmodel) ...
$http.get("../api/comm/" + commId
).success(function (resp) {
fixDates(resp);
vm.comm = resp;
});
(I need not check the string length, but I figured it would spare some cpu cycles by not running the regex if the string is obviously not a date)
//2015-10-01T00:00:00-04:00
//2015-11-20T18:15:56.6229516-05:00
var isDate = new RegExp("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{7})?-\\d{2}:00");
function fixDates(json) {
for (i in json)
if (typeof (json[i]) == "object")
fixDates(json[i]);
else if (typeof (json[i]) == "string" && (json[i].length == 25 || json[i].length == 33) && isDate.test(json[i]))
json[i] = new Date(json[i]);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With