Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.js <input type="date"> change format of submitted value

<label>From</label>
<input type="date"  ng-model="startDate"/>
<label>To</label>
<input type="date" ng-model="endDate"/>

<button class="btn btn-success" ng-click="getStatistics(startDate, endDate)">Update</button>

**JS***

$scope.getStatistics = function(startDate, endDate) {
    $http.get('/admin/api/stats?start=' + startDate + '&end=' + endDate).success(function(data) {
        $scope.stats = data;
    });
}

The code above push startDate and endDate value on url, but the problem i have is that the submitted value is like 2014-12-01 and i want my format to be 01-05-2014

Any suggestions?

like image 897
user3531335 Avatar asked Oct 02 '22 00:10

user3531335


1 Answers

Unfortunately, browsers that implement a specific element type for handling dates (such as Chrome) use the OS date format, and none that I'm aware of let you change the format (it's not even in the W3C spec). Furthermore, if the browser does not support it (most of them), it uses a regular text input but only accepts data in ISO-8601 format, which makes matters worse.

Personally, I avoid type="date" because as is, it's pretty much worthless, unless you're on a mobile device that supports it (such as iOS). So if you can, use a text input, and if you want it to convert the text value into a date object to assign to your model, as well as reformat it upon being updated, you'll need to find or write a directive to do this. There is the UI-Bootstrap date picker, but it does not reformat the date for you and brings along more stuff than perhaps you need. There may be others, too.

However, in the spirit of answering your question, I put together a demo directive that both reformats the entered date to the format of your choice (using Angular's $date filter). It'll reformat on paste, blur/change, or after a brief pause of inactivity after typing a date in (the latter may not work particularly well in the real world, but it looks kinda cool. take it out if it's weird). The other shortfall is it uses the browser's default mechanism for parsing a Date. If this is insufficient, replace it with something that is. I'm sure it's far from production-ready, but it's a start. If it's useful enough, I'll turn it into a formal module on Github.

angular.module("demo.directives", [])
  .directive('date', ['$filter', '$timeout', function($filter, $timeout) {
    return {
      restrict: 'A',
      require: '?^ngModel',
      link: function($scope, $element, $attrs, ngModel) {
        var format = $attrs.dateFormat || 'short', // default date format
             validityName = 'date'; // change the name to whatever you want to use to check errors

        // called by the directive to render the first time, and also on events when the value is changed 
        var formatter = function() {
            var date =  ngModel.$modelValue ? 
              $filter('date')(ngModel.$modelValue, format) : 
              ngModel.$viewValue;

            $element.val(date);
        };

         // parse the value when it is being set from the view to the model
         ngModel.$parsers.unshift(function(value) {
            //  you may wish to use a more advanced date parsing module for better results
            var date = new Date(value);

            if (isNaN(date)) { 
              // invalid date, flag invalid and return undefined so we don't set the model value
              ngModel.$setValidity(validityName, false);
              return undefined;
            }

            // clear invalid flag
            ngModel.$setValidity(validityName, true);

            return date;
         });

         // used by ngModel to display to render the directive initially; we'll just reformat
         ngModel.$render = formatter;

         var handle;

         // trigger the formatter on paste
         $element.on('paste cut', function() {
           if (handle) $timeout.cancel(handle);
           handle = $timeout(formatter, 0); // needs to break out of the current context to work
         })
         // you can axe this whole event if you don't like the reformat after a pause
         $element.on('keydown', function() {
           if (handle) $timeout.cancel(handle);
           handle = $timeout(formatter, 750);
         })
         // trigger the formatter on blur
         $element.on('blur change', formatter);
      }
    };
  }]);

Usage:

Include the directive from this plunk in module, then in your HTML use

 <input type="text" date date-format="short" ng-model="myDateValue" />
like image 91
moribvndvs Avatar answered Oct 13 '22 12:10

moribvndvs