Why is my date input field in AngularJS throwing type error?

Problem

The error occurs when I display the populated, editable form to the user (not when a user enters in data and submits). The data is coming from MySQL over REST/JSON in the service shown below:

HTML:

<input class="form-control" type="date" name="dateInput" id="dateOfBirth" 
                   ng-model="user.dateOfBirth">

CCONTROLLER:

.controller('EditCtrl', function ($scope, $routeParams, UserDetail, $window) {
        $scope.user = UserDetail.find({}, {'id': $routeParams.id});
}

SERVICE:

service.factory('UserDetail', function ($resource) {

    return $resource(
        'http://localhost:8080/ClearsoftDemoBackend/webresources/clearsoft.demo.users/:id',
        {id: '@id'},
    {
    find: {method: 'GET'},

    });
});

ERROR:

Error: [ngModel:datefmt] Expected 2010-05-13T00:00:00-04:00 to be a date

Problem courtesy of: vt97john

Solution

Its because that is not a valid date according to Angular. Check out the doc on input[date] for their note on date validation. For it to be a date it should be in the format of YYYY-MM-DD.

Solution courtesy of: Matthew Green

Discussion

For date value in an array one can use this as:

    var dates = [
      { id: "1" , date: "2015-04-20T11:24:20.882Z"},
      { id: "2" , date: "2015-05-20T11:24:20.882Z"},
      { id: "3" , date: "2015-06-20T11:24:20.882Z"},
    ];

      function dateStringToObject (data) {
        for(var i=0; i < data.length; i++ ){
          data[i].date = new Date(data[i].date);
          }

        return data;
      }

   dateStringToObject(dates);
Discussion courtesy of: Akash Saxena

AngularJS 1.3 adds to input [date | datetime-local ] fields a new formatter/parser that checks that the model is a Date Object and throw the datefmt exception.

if (value && !isDate(value)) {
    throw $ngModelMinErr('datefmt', 'Expected `{0}` to be a date', value);

This issue is not present at previos versions and I suggest get in consideration on upgrade to avoid big nightmares.

A workaroud is to reset default formatters/parser with a custom dateFormat directive and use momentjs to format,parse strings to Date.

define(['directives/directives','momentjs'], function(directives,momentjs) {
directives.directive('dateFormat', function() {
      return {
        require: 'ngModel',
        link: function(scope, element, attr, ngModelCtrl) {
          var format=attr.dateFormat;
          //Angular 1.3 insert a formater that force to set model to date object, otherwise throw exception.
          //Reset default angular formatters/parsers
          ngModelCtrl.$formatters.length=0;
          ngModelCtrl.$parsers.length=0;

          ngModelCtrl.$formatters.push(function(valueFromModel) {
             //return how data will be shown in input
              if(valueFromModel){
                 // For momentjs > 2.9 moment global va is not defined use momentjs instead of moment.
                  return moment(valueFromModel).format(format);
              }
              else
                  return null;
          });
          ngModelCtrl.$parsers.push(function(valueFromInput) {
              if(valueFromInput){
                  //For momentjs > 2.9 moment global va is not defined use momentjs instead of moment.
                  return moment(valueFromInput,format).toDate();
              }
              else 
                  return null;
          });
        }
      };
    });
});

UPDATE With momentjs > 2.9 take in consideration that the moment global var are not defined.

2.9 "Deprecation warning: Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release."

With AMD need use momentjs instead of moment. i.e:

return momentjs(valueFromModel).format(format);
Discussion courtesy of: pdorgambide

In your api

$date = date("Y-m-d");
$new_date = date("c",strtotime($date));
echo json_encode(array("date"=>$new_date));

In your controller

/* var date 
* this is value from your api
*/
$scope.date = new Date(date);
Discussion courtesy of: Same

Basically its not about the format, it want a valid new Date() object in ISO format ,so whatever you get response ,just do a new Date and angular will be happy , i got this when i parsed the exception message caused by angular

https://docs.angularjs.org/error/ngModel/datefmt?p0=2015-11-24

Discussion courtesy of: Pranay Dutta

This recipe can be found in it's original form on Stack Over Flow.