Angular-UI date picker is in invalid state when specified the date format as 'd-M-yyyy' and ng-model with a string value as “2014-08-31T00:00:00Z”

后端 未结 7 2119
借酒劲吻你
借酒劲吻你 2021-02-15 23:49

I am getting a date time value from asp.net mvc controller as \"2014-08-31T00:00:00Z\". When I bind this value to my angular-ui datepicker control it\'s state is showing as ng-i

相关标签:
7条回答
  • 2021-02-16 00:04

    Just wanted to add my solution to this stack.

    app.directive('formatDate', function (dateFilter, uibDateParser, uibDatepickerPopupConfig) {
        return {
            restrict: 'A',
            priority: 1,
            require: 'ngModel',
            link: function (scope, element, attr, ngModel) {
                var dateFormat = attr.uibDatepickerPopup || uibDatepickerPopupConfig.datepickerPopup;
                ngModel.$validators.date = function(modelValue, viewValue) {
                    var value = viewValue || modelValue;
    
                    if (!attr.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 = new Date(value);
                        return !isNaN(date);
                    } else {
                        return false;
                    }
                }
                ngModel.$formatters.push(function(value) {
                    return new Date(value);
                });
            }
        };
    });
    
    0 讨论(0)
  • 2021-02-16 00:10

    I don't have enough reputation to comment under Chet's answer but thanks so much this solution worked for me as well! I don't know your Github handle to tag you in the issue but I submitted a Github issue under Angular UI to help others find the solution and hopefully get Angular UI guys to look into it. Thanks again!

    https://github.com/angular-ui/bootstrap/issues/4554

    0 讨论(0)
  • 2021-02-16 00:10

    To use formatted date string instead of Date object as ng-model for Angular Datepicker, you need to create a wrapper directive. The wrapper directive will parse your string into Date object and pass it to the datepicker. When you select a date, it is converted from Date back into string. Here is an example (Plunker):

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

    0 讨论(0)
  • 2021-02-16 00:17

    I solved the problem by converting string to valid javascript formt in directive:

    see here: Datepicker-popup formatting not working when value set initially in scope

    0 讨论(0)
  • 2021-02-16 00:19

    A couple of notes here:

    1. First, the datepicker directive requires that the ng-model be a Date object. This is documented here.
    2. Second, the solution posted (and accepted) by Chet above is VERY heavy-handed as it takes EVERY date string received in an HTTP response and converts it to a Date object if it matches a hard-coded pattern. This is not flexible nor is it easily testable. It will not be the right solution for most people.

    If, in your system, global date string conversion is the right behavior, the proper Angular design would be to create a service that does this for you. This leads me to...

    We've (Angular UI Bootstrap) provided a mechanism for converting date strings into Date objects via the dateParser service. You can see the source code here. NB: this service name becomes deprecated and changed to uibDateParser with the 0.14.0 release.

    0 讨论(0)
  • 2021-02-16 00:20

    I had the same problem. The issue is that Angular is expecting an actual date object, not a string representation of the date. After doing a bunch of research I ended up adding a transformReponse to the $httpProvider which checks all string objects to see if they can be converted to a date, and if so actually converting them.

    angular.module('test')
    .config(['$httpProvider', function ($httpProvider) {
    
        // ISO 8601 Date Pattern: YYYY-mm-ddThh:MM:ss
        var dateMatchPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
    
       var convertDates = function (obj) {
          for (var key in obj) {
             if (!obj.hasOwnProperty(key)) continue;
    
             var value = obj[key];
             var typeofValue = typeof (value);
    
             if (typeofValue === 'object') {
                // If it is an object, check within the object for dates.
                convertDates(value);
             } else if (typeofValue === 'string') {
                if (dateMatchPattern.test(value)) {
                   obj[key] = new Date(value);
                }
             }
          }
       }
    
       $httpProvider.defaults.transformResponse.push(function (data) {
          if (typeof (data) === 'object') {
             convertDates(data);
          }
    
          return data;
       });
    }])
    
    0 讨论(0)
提交回复
热议问题