Jen Jen - 1 month ago 7x
AngularJS Question

Simple angularjs date input

I have an edit page for an event and one of my fields is a date. In some browsers it seems to act like a plain text box (IE8), however in chrome it displays "dd/mm/yyyy" and if you click on it it has some additional options for setting the date.

My issue though is on the edit page it's not populating the existing date (I imagine because it's not in the correct format?). The MVC controller returns the data in this format "2014-03-08T00:00:00" (just using basic CRUD controller actions).

<form name="form" class="form-horizontal">
<div class="control-group" ng-class="{error: form.EventDate.$invalid}">
<label class="control-label" for="EventDate">Event Date</label>
<div class="controls">
<input type="date" ng-model="item.EventDate" id="EventDate">
<div class="form-actions">
<button ng-click="save()" class="btn btn-primary">
<a href="#/" class="btn">Cancel</a>

I've seen quite a few posts on using directives and watches, but that seems complicated. I would have thought there would have been a relatively simple way of formatting the model data so that it displays in the right format and works as expected. I don't mind if Chrome gives a different experience than other browsers - it's just a simple internal user website. I just don't like that it's not prepopulating the date when I edit a record.


If you want to populate the field with an initial value, then the following will work

$scope.myDate = new Date('2014-03-08T00:00:00');

<input type="date" ng-init="model=(myDate | date:'yyyy-MM-dd')" ng-model="model" />

However, I strongly recommend creating a custom date field directive.

A custom input field directive offers the following benefits:

  1. Two-way binding between the model and the view. For example, when you enter a valid date in the input field, it will automatically assign a javascript date to the model; and when you assign a valid javascript date as the model, it will automatically format it in the text field.
  2. Form validation support. When you enter an invalid date, you can set an $error flag, which can be used in your view bindings (i.e. displaying an error message). Setting an error flag will also set form.$valid to false so that you can conditionally submit the form to the server.

There are three basic things to consider when implementing a custom date directive:

  1. A parser that will parse the input text and return the model (in this case, a javascript date).
  2. A formatter that will format the model and display it in the text field.
  3. Setting of an optional validation flag which can be used in the UI for custom form validation.

Date Directive:

myApp.directive('dateField', function($filter) {
  return {
      require: 'ngModel',
      link: function(scope, element, attrs, ngModelController) {
           ngModelController.$parsers.push(function(data) {

              //View -> Model
              var date = Date.parseExact(data,'yyyy-MM-dd');

              // if the date field is not a valid date 
              // then set a 'date' error flag by calling $setValidity
              ngModelController.$setValidity('date', date!=null);
              return date == null ? undefined : date;
           ngModelController.$formatters.push(function(data) {
              //Model -> View
              return $filter('date')(data, "yyyy-MM-dd");

Note: For parsing dates, this directive uses Date.js (an external library).


.error {
.error-border {
  border: solid 2px red;


<form name="myForm">
     <input ng-class="{'error-border': myForm.myDate.$}" type="date"
            name="myDate" ng-model="myDate" date-field />
              <span ng-show="myForm.myDate.$" class="error">
                  Please enter a valid date!!!
         <br /> Raw Date: {{myDate}} 
         <br /> Formatted Nicely: {{ myDate | date:'yyyy, MMMM dd'}}    
         <br /> Is Valid Date? {{ !myForm.myDate.$}}
         <br /> Is Form Valid? {{ myForm.$valid }}


myApp.controller('ctrl', function($scope) {
    $scope.myDate = new Date('2014-03-08T00:00:00');

Demo JS Fiddle with Date.js
Demo JS Fiddle with Moment.js