4

I am using $http.get in a service in to fetch JSON data. One of my object properties in the returned JSON is a date which is not being parsed by AngularJS. I need to bind this property to a date field and I am currently working around it by manually converting the JSON string to a javascript date after fetching the AJAX data as shown below

app.service('MainService', function(){
  var self = this;
  self.jsonDate = null;
  self.parsedDate = null;

  // this function will get JSON data from an API in production
  self.getData = function(){
    var jsonData = "2014-06-13T16:00:00";

    // Angular does not convert my JSON data properties into dates
    self.jsonDate = jsonData;

    // I can work around this by forcing my dates to be parsed
    self.parsedDate = moment(jsonData).toDate();
  }
});

Is there a cleaner way of doing this? I built a filter that converts a string to a date

app.filter('stringToDate', function () {
    return function (input) {
        if (!input)
            return null;

        var date = moment(input);
        return date.isValid() ? date.toDate() : null;
    };
});

The filter works great if I use it as shown below

<span ng-bind="service.jsonDate | stringToDate | date:'MM/dd/yy'"></span>

but it does not work if I try to use it with ng-model as shown below

<input type="date" ng-model="service.jsonDate | stringToDate"/>

Can a filter be used with ng-model or do I need to stick with manually converting properties to dates? I have a plunker here that demonstrates my current code

http://plnkr.co/edit/pVaDbjIjtnKaYqrjAd0D?p=preview

1
  • Updated answer with custom directive option. Commented Jun 14, 2014 at 7:32

1 Answer 1

6

Plunker Demo Here

There are few ways you can do this:

  1. Use the filter in ng-init to initialize a scope variable, then bind the ng-model to the scope variable.

    <body ng-controller="MainCtrl" ng-init="mydate = (service.jsonDate | stringToDate)">
        <label>Raw JSON Date</label>
        <input type="date" data-ng-model="service.jsonDate"/><br/><br/>
    
        <label>Parsed JSON date</label>
        <input type="date" data-ng-model="mydate"/>
     </body>
    
  2. Use the $filter service to manually invoke the stringToDate filter in your controller:

    app.controller('MainCtrl', function($scope, $filter, MainService) {
        $scope.service = MainService;
    
        // fetch data from service
        $scope.service.getData();
    
        $scope.parsedDate = $filter('stringToDate')(MainService.jsonDate);
    
    });
    

    And then bind the variable to your ng-model:

    <input type="date" data-ng-model="parsedDate"/>
    

    [EDIT]

  3. Use a custom directive which relies on an ng-model that is raw JSON. Add a formatter to convert the model to a date string; and a parser to convert the date string back to the model. The advantage of this approach is that the two-way model binding is maintained. When you update the text box with a valid date string, it automatically updates the raw JSON model (and vice versa).

In the plunker example, try entering a valid date string, and notice how the model automatically changes.

Directive:

   app.directive('jsonDate', function($filter) {
      return  {
          restrict: 'A',
          require: 'ngModel',
          link: function (scope, element, attrs, ngModel) {

             //format text going to user (model to view)
             ngModel.$formatters.push(function(value) {
                var date = $filter('stringToDate')(value);
                return date.toString();
             });

             //format text from the user (view to model)
             ngModel.$parsers.push(function(value) {
                var date = new Date(value);
                if (!isNaN( date.getTime())) { 
                   return moment(date).format();
                }
             });
         }
     }

HTML:

 <input type="date" data-ng-model="service.jsonDate" json-date/>

This last example allows you to bind an ngModel to a json date string and have it display a formatted date. When the user enters a valid formatted date, it automatically updates the json date string model that its bound to

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for elaborated answer. one query though, I am also trying example 3 from last many hours, but it is not working, after html get loaded it does not show date. I visited your plunker, and it is also not showing date anymore.
On your plunker, when .html page loaded on browser, I am expecting it to show the date, but why it is not the case?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.