Syntax date string for Date object when loading Angular UI Bootstrap Datepicker

I am using Angular UI Bootstrap Datepicker: https://angular-ui.imtqy.com/bootstrap/#/datepicker

When I process the form using the data received from the server, there is a problem with the datetime fields. My datepicker parameter is as follows:

<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 a datetime response as a JSON string:

 { ... startedAt: "2015-05-29T02:00:00+0200" } 

When I assign response data to the model $scope.item = response; , the input field of the date picker is displayed correctly (the correct date is selected and it is correctly formatted in the selected format). The problem is that validation fails. I get:

 itemForm.startedAt.$invalid == true 

I noticed that the data bound to the datepicker field should be a Date object, not a string (when I select a new date from datepicker, $scope.item.startedAt is Date )

I managed to get around this problem and do it in the controller:

 $scope.item = response; $scope.item.startedAt = new Date($scope.item.startedAt); 

This works like this ... But I would not want to manually convert the do date string every time I get a response from the server. I tried to create a directive that I can assign to the date input field so that it changes 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, this works because now I see the Date object when I output the model in my opinion: {{item.startedAt}} . However, the verification still fails ! I suspect this is some problem with me, understanding how the data flows between the model and the view, and how UT Bootstrap connects.

Also, when I change my directive from $formatters.push to $formatters.unshift , the check works fine, but the datepicker does not format my datetime (insted of niceformattet yyyy-MM-dd I see the ISO line inside the input)

+6
source share
3 answers

Since this is the intentional behavior of angular -ui-bootstrap datepicker ( https://github.com/angular-ui/bootstrap/issues/4690 ), I ended up using the Angular / factory and moment .

The dateConverter service can be entered globally to intercept all HTTP requests / responses or only in the required controllers.

Here, I use the Restangular library to process the REST API request, therefore the response.plain() method, which only accepts object properties, not Restangular methods / properties.

 var Services = angular.module('app.Services', []); Services .factory('dateConverter', ['dateFilter', function (dateFilter) { var dateConverter = {}; dateConverter.prepareResponse = function (response) { for(prop in response.plain()) { if (response.hasOwnProperty(prop)) { if(moment(response[prop], moment.ISO_8601, true).isValid()) { response[prop] = new Date(response[prop]); } } } return response; }; dateConverter.prepareRequest = function (item) { for(prop in item.plain()) { if (item.hasOwnProperty(prop)) { if(angular.isDate(item[prop])){ item[prop] = dateFilter(item[prop] , "yyyy-MM-ddTHH:mm:ssZ") } } } return item; }; return dateConverter; }]) ; 
+1
source

It broke like Angular.UI.Bootstrap v0.13.2 (8-2-2015) Decreasing to 0.13.1 works where I am stuck today.

Wesleycho says this was intentionally done https://github.com/angular-ui/bootstrap/issues/4690

I am ready for other choices that support strings, if anyone has a suggestion

... shortly after posting this question, I took 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 matches one of two consecutive date formats that I saw, and then I have a recursive javascript function to move the json tree and replace these Date () strings. You would call it before entering $ scope (or viewmodel) ...

 $http.get("../api/comm/" + commId ).success(function (resp) { fixDates(resp); vm.comm = resp; }); 

(I don’t need to check the length of the string, but I figured this would save some processor cycles by not running the regex if the string is clearly 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]); }; 
0
source

you can convert String to Date into a relay transformer, something like this

 RestangularConfigurer .addElementTransformer('<RESTRESOURCENAME>', false, function (element) { element.createDate = new Date(element.createDate); return element; }) 
0
source

All Articles