[angularjs] Angular bootstrap datepicker date format does not format ng-model value

I am using bootstrap date-picker in my angular application. However when I select a date from that date-picker underlying ng-model that I have bind gets updated I want that ng-model in one date format 'MM/dd/yyyy'. but it every times makes date like this

"2009-02-03T18:30:00.000Z"

instead of

02/04/2009

I have created a plunkr for the same plunkr link

My Html and controller code is like below

<!doctype html>
<html ng-app="plunker">
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.js"></script>
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
    <script src="example.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>

<div ng-controller="DatepickerDemoCtrl">
    <pre>Selected date is: <em>{{dt | date:'MM/dd/yyyy' }}</em></pre>
    <p>above filter will just update above UI but I want to update actual ng-modle</p>


    <h4>Popup</h4>
    <div class="row">
        <div class="col-md-6">
            <p class="input-group">
              <input type="text" class="form-control"
              datepicker-popup="{{format}}" 
              ng-model="dt"
              is-open="opened" min-date="minDate"
              max-date="'2015-06-22'" 
              datepicker-options="dateOptions" 
              date-disabled="disabled(date, mode)" 
              ng-required="true" close-text="Close" />
              <span class="input-group-btn"> 
                <button type="button" class="btn btn-default" ng-click="open($event)">
                <i class="glyphicon glyphicon-calendar"></i></button>
              </span>
            </p>
        </div>
    </div>
    <!--<div class="row">
        <div class="col-md-6">
            <label>Format:</label> <select class="form-control" ng-model="format" ng-options="f for f in formats"><option></option></select>
        </div>
    </div>-->

    <hr />
    {{dt}}
</div>
  </body>
</html>

Angular controller

angular.module('plunker', ['ui.bootstrap']);
var DatepickerDemoCtrl = function ($scope) {


  $scope.open = function($event) {
    $event.preventDefault();
    $event.stopPropagation();

    $scope.opened = true;
  };

  $scope.dateOptions = {
    formatYear: 'yy',
    startingDay: 1
  };


  $scope.format = 'dd-MMMM-yyyy';
};

Thanks in advance for review my question.

UPDATE

I am calling below method for posting my data and VAR is array of size 900 which contains date-picker variables.

public SaveCurrentData(formToSave: tsmodels.ResponseTransferCalculationModelTS) {

        var query = this.EntityQuery.from('SaveFormData').withParameters({
            $method: 'POST',
            $encoding: 'JSON',
            $data: {
                VAR: formToSave.VAR,
                X: formToSave.X,
                CurrentForm: formToSave.currentForm,
            }
        });

        var deferred = this.q.defer();

        this.manager.executeQuery(query).then((response) => {
            deferred.resolve(response);
        }, (error) => {
                deferred.reject(error);
            });

        return deferred.promise;
    }

The answer is


Although similar answers have been posted I'd like to contribute what seemed to be the easiest and cleanest fix to me. Assuming you are using the AngularUI datepicker and your initial value for the ng-Model does not get formatted simply adding the following directive to your project will fix the issue:

angular.module('yourAppName')
.directive('datepickerPopup', function (){
    return {
        restrict: 'EAC',
        require: 'ngModel',
        link: function(scope, element, attr, controller) {
      //remove the default formatter from the input directive to prevent conflict
      controller.$formatters.shift();
  }
}
});

I found this solution in the Github AngularUI issues and therefore all credit goes to the people over there.


Finally I got work around to the above problem. angular-strap has exactly the same feature that I am expecting. Just by applying date-format="MM/dd/yyyy" date-type="string" I got my expected behavior of updating ng-model in given format.

<div class="bs-example" style="padding-bottom: 24px;" append-source>
    <form name="datepickerForm" class="form-inline" role="form">
      <!-- Basic example -->
      <div class="form-group" ng-class="{'has-error': datepickerForm.date.$invalid}">
        <label class="control-label"><i class="fa fa-calendar"></i> Date <small>(as date)</small></label>
        <input type="text"  autoclose="true"  class="form-control" ng-model="selectedDate" name="date" date-format="MM/dd/yyyy" date-type="string" bs-datepicker>
      </div>
      <hr>
      {{selectedDate}}
     </form>
</div>

here is working plunk link


I can fix this by adding below code in my JSP file. Now both model and UI values are same.

<div ng-show="false">
    {{dt = (dt | date:'dd-MMMM-yyyy') }}
</div>  

I ran into the same problem and after a couple of hours of logging and investigating, I fixed it.

It turned out that for the first time the value is set in a date picker, $viewValue is a string so the dateFilter displays it as is. All I did is parse it into a Date object.

Search for that block in ui-bootstrap-tpls file

  ngModel.$render = function() {
    var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
    element.val(date);

    updateCalendar();
  };

and replace it by:

  ngModel.$render = function() {
    ngModel.$viewValue = new Date(ngModel.$viewValue);
    var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
    element.val(date);

    updateCalendar();
  };

Hopefully this will help :)


The format specified through datepicker-popup is just the format for the displayed date. The underlying ngModel is a Date object. Trying to display it will show it as it's default, standard-compliant rapresentation.

You can show it as you want by using the date filter in the view, or, if you need it to be parsed in the controller, you can inject $filter in your controller and call it as $filter('date')(date, format). See also the date filter docs.


You can make use of $parsers as shown below,this solved it for me.

window.module.directive('myDate', function(dateFilter) {
  return {
    restrict: 'EAC',
    require: '?ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$parsers.push(function(viewValue) {
        return dateFilter(viewValue,'yyyy-MM-dd');
      });
    }
  };
});

HTML:

<p class="input-group datepicker" >
  <input
     type="text"
     class="form-control"
     name="name"
     datepicker-popup="yyyy-MM-dd"
     date-type="string"
     show-weeks="false"
     ng-model="data[$parent.editable.name]" 
     is-open="$parent.opened"
     min-date="minDate"
     close-text="Close"
     ng-required="{{editable.mandatory}}"
     show-button-bar="false"
     close-on-date-selection="false"
     my-date />
  <span class="input-group-btn">
    <button type="button" class="btn btn-default" ng-click="openDatePicker($event)">
      <i class="glyphicon glyphicon-calendar"></i>
    </button>
  </span>
</p>

The datepicker (and datepicker-popup) directive requires that the ng-model be a Date object. This is documented here.

If you want ng-model to be a string in specific format, you should create a wrapper directive. Here is an example (Plunker):

_x000D_
_x000D_
(function () {_x000D_
    'use strict';_x000D_
_x000D_
    angular_x000D_
        .module('myExample', ['ngAnimate', 'ngSanitize', 'ui.bootstrap'])_x000D_
        .controller('MyController', MyController)_x000D_
        .directive('myDatepicker', myDatepickerDirective);_x000D_
_x000D_
    MyController.$inject = ['$scope'];_x000D_
_x000D_
    function MyController ($scope) {_x000D_
      $scope.dateFormat = 'dd MMMM yyyy';_x000D_
      $scope.myDate = '30 Jun 2017';_x000D_
    }_x000D_
_x000D_
    myDatepickerDirective.$inject = ['uibDateParser', '$filter'];_x000D_
_x000D_
    function myDatepickerDirective (uibDateParser, $filter) {_x000D_
        return {_x000D_
            restrict: 'E',_x000D_
            scope: {_x000D_
                name: '@',_x000D_
                dateFormat: '@',_x000D_
                ngModel: '='_x000D_
            },_x000D_
            required: 'ngModel',_x000D_
            link: function (scope) {_x000D_
_x000D_
                var isString = angular.isString(scope.ngModel) && scope.dateFormat;_x000D_
_x000D_
                if (isString) {_x000D_
                    scope.internalModel = uibDateParser.parse(scope.ngModel, scope.dateFormat);_x000D_
                } else {_x000D_
                    scope.internalModel = scope.ngModel;_x000D_
                }_x000D_
_x000D_
                scope.open = function (event) {_x000D_
                    event.preventDefault();_x000D_
                    event.stopPropagation();_x000D_
                    scope.isOpen = true;_x000D_
                };_x000D_
_x000D_
                scope.change = function () {_x000D_
                    if (isString) {_x000D_
                        scope.ngModel = $filter('date')(scope.internalModel, scope.dateFormat);_x000D_
                    } else {_x000D_
                        scope.ngModel = scope.internalModel;_x000D_
                    }_x000D_
                };_x000D_
_x000D_
            },_x000D_
            template: [_x000D_
                '<div class="input-group">',_x000D_
                    '<input type="text" readonly="true" style="background:#fff" name="{{name}}" class="form-control" uib-datepicker-popup="{{dateFormat}}" ng-model="internalModel" is-open="isOpen" ng-click="open($event)" ng-change="change()">',_x000D_
                    '<span class="input-group-btn">',_x000D_
                        '<button class="btn btn-default" ng-click="open($event)">&nbsp;<i class="glyphicon glyphicon-calendar"></i>&nbsp;</button>',_x000D_
                    '</span>',_x000D_
                '</div>'_x000D_
            ].join('')_x000D_
        }_x000D_
    }_x000D_
_x000D_
})();
_x000D_
<!DOCTYPE html>_x000D_
<html>_x000D_
_x000D_
  <head>_x000D_
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>_x000D_
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>_x000D_
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>_x000D_
    <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>_x000D_
    <script src="example.js"></script>_x000D_
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">_x000D_
  </head>_x000D_
_x000D_
  <body ng-app="myExample">_x000D_
    <div ng-controller="MyController">_x000D_
      <p>_x000D_
        Date format: {{dateFormat}}_x000D_
      </p>_x000D_
      <p>_x000D_
        Value: {{myDate}}_x000D_
      </p>_x000D_
      <p>_x000D_
        <my-datepicker ng-model="myDate" date-format="{{dateFormat}}"></my-datepicker>_x000D_
      </p>_x000D_
    </div>_x000D_
  </body>_x000D_
_x000D_
</html>
_x000D_
_x000D_
_x000D_


With so many answers already written, Here's my take.

With Angular 1.5.6 & ui-bootstrap 1.3.3 , just add this on the model & you are done.

ng-model-options="{timezone: 'UTC'}" 

Note: Use this only if you are concerned about the date being 1 day behind & not bothered with extra time of T00:00:00.000Z

Updated Plunkr Here :

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


All proposed solutions didn't work for me but the closest one was from @Rishii.

I'm using AngularJS 1.4.4 and UI Bootstrap 0.13.3.

.directive('jsr310Compatible', ['dateFilter', 'dateParser', function(dateFilter, dateParser) {
  return {
    restrict: 'EAC',
    require: 'ngModel',
    priority: 1,
    link: function(scope, element, attrs, ngModel) {
      var dateFormat = 'yyyy-MM-dd';

      ngModel.$parsers.push(function(viewValue) {
        return dateFilter(viewValue, dateFormat);
      });

      ngModel.$validators.date = function (modelValue, viewValue) {
        var value = modelValue || viewValue;

        if (!attrs.ngRequired && !value) {
          return true;
        }

        if (angular.isNumber(value)) {
          value = new Date(value);
        }

        if (!value) {
          return true;
        }
        else if (angular.isDate(value) && !isNaN(value)) {
          return true;
        }
        else if (angular.isString(value)) {
          var date = dateParser.parse(value, dateFormat);
          return !isNaN(date);
        }
        else {
          return false;
        }
      };
    }
  };
}])

Defining a new directive to work around a bug is not really ideal.

Because the datepicker displays later dates correctly, one simple workaround could be just setting the model variable to null first, and then to the current date after a while:

$scope.dt = null;
$timeout( function(){
    $scope.dt = new Date();
},100);

Steps to change the default date format of ng-model

For different date formats check the jqueryui datepicker date format values here for example I have used dd/mm/yy

Create angularjs directive

angular.module('app', ['ui.bootstrap']).directive('dt', function () {
return {
    restrict: 'EAC',
    require: 'ngModel',
    link: function (scope, element, attr, ngModel) {
        ngModel.$parsers.push(function (viewValue) {
           return dateFilter(viewValue, 'dd/mm/yy');
        });
    }
 }
});

Write dateFilter function

function dateFilter(val,format) {
    return $.datepicker.formatDate(format,val);
}

In html page write the ng-modal attribute

<input type="text" class="form-control" date-type="string"  uib-datepicker-popup="{{format}}" ng-model="src.pTO_DATE" is-open="popup2.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" show-button-bar="false" show-weeks="false" dt />

After checking the above answers, I came up with this and it worked perfectly without having to add an extra attribute to your markup

angular.module('app').directive('datepickerPopup', function(dateFilter) {
    return {
        restrict: 'EAC',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {
            ngModel.$parsers.push(function(viewValue) {
                return dateFilter(viewValue, 'yyyy-MM-dd');
            });
        }
    }
});

You may use formatters after picking value inside your datepicker directive. For example

angular.module('foo').directive('bar', function() {
    return {
        require: '?ngModel',
        link: function(scope, elem, attrs, ctrl) {
            if (!ctrl) return;

            ctrl.$formatters.push(function(value) {
                if (value) {
                    // format and return date here
                }

                return undefined;
            });
        }
    };
});

LINK.


Examples related to angularjs

AngularJs directive not updating another directive's scope ERROR in Cannot find module 'node-sass' CORS: credentials mode is 'include' CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 Print Html template in Angular 2 (ng-print in Angular 2) $http.get(...).success is not a function Angular 1.6.0: "Possibly unhandled rejection" error Find object by its property in array of objects with AngularJS way Error: Cannot invoke an expression whose type lacks a call signature

Examples related to datepicker

Angular-Material DateTime Picker Component? $(...).datepicker is not a function - JQuery - Bootstrap Uncaught TypeError: $(...).datepicker is not a function(anonymous function) Get date from input form within PHP Angular bootstrap datepicker date format does not format ng-model value jQuery Datepicker close datepicker after selected date bootstrap datepicker setDate format dd/mm/yyyy bootstrap datepicker change date event doesnt fire up when manually editing dates or clearing date Clear the value of bootstrap-datepicker Disable future dates after today in Jquery Ui Datepicker

Examples related to angular-ui

Angular ui-grid dynamically calculate height of the grid How to pass parameters using ui-sref in ui-router to controller Angular bootstrap datepicker date format does not format ng-model value How to detect browser using angularjs? Injecting $scope into an angular service function() How to reload the current state? How to achieve pagination/table layout with Angular.js? How to use a keypress event in AngularJS? How to detect current state within directive Check if a input box is empty

Examples related to angular-ui-bootstrap

How to add bootstrap in angular 6 project? Angular bootstrap datepicker date format does not format ng-model value How do I increase modal width in Angular UI Bootstrap? Responsive dropdown navbar with angular-ui bootstrap (done in the correct angular kind of way) Invoking modal window in AngularJS Bootstrap UI using JavaScript

Examples related to angular-ngmodel

Angular error: "Can't bind to 'ngModel' since it isn't a known property of 'input'" Get user input from textarea AngularJs - ng-model in a SELECT Angular bootstrap datepicker date format does not format ng-model value Radio Buttons ng-checked with ng-model How to set a selected option of a dropdown list control using angular JS Ng-model does not update controller value What's the difference between ng-model and ng-bind AngularJS : ng-model binding not updating when changed with jQuery