首页 文章

Angular bootstrap datepicker日期格式不格式化ng-model值

提问于
浏览
60

我在角度应用程序中使用bootstrap日期选择器 . 然而,当我从该日期选择器中选择一个日期选择器时,我已经更新了绑定的ng-model,我想要一个日期格式为'MM / dd / yyyy'的ng-model . 但它每次都像这样约会

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

代替

02/04/2009

我为同一个创造了一个plunkr plunkr link

我的Html和控制器代码如下所示

<!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';
};

在此先感谢您审核我的问题 .

UPDATE

我在下面调用方法来发布我的数据,VAR是大小为900的数组,其中包含日期选择器变量 .

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;
    }

13 回答

  • 0

    虽然已经公布了类似的答案,但我想为我做出最简单,最干净的解决方案 . Assuming you are using the AngularUI datepicker 并且ng-Model的初始值没有格式化,只需将以下指令添加到项目中就可以解决问题:

    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();
      }
    }
    });
    

    我在Github AngularUI issues找到了这个解决方案,因此所有信用都归于那边的人 .

  • 100

    您可以使用$解析器,如下所示,这为我解决了它 .

    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>
    
  • 3

    我遇到了同样的问题,经过几个小时的记录和调查,我修复了它 .

    事实证明,这个值第一次在日期选择器中设置,$ viewValue是一个字符串,因此dateFilter按原样显示它 . 我所做的就是将其解析为Date对象 .

    在ui-bootstrap-tpls文件中搜索该块

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

    并将其替换为:

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

    希望这会有所帮助:)

  • 0

    通过 datepicker-popup 指定的 format 只是 the format for the displayed date . 底层 ngModel 是一个Date对象 . 试图显示它将显示它是默认的,符合标准的表示 .

    您可以在视图中使用 date 过滤器显示它,或者,如果您需要在控制器中解析它,可以在控制器中注入 $filter 并将其称为 $filter('date')(date, format) . 另见date filter docs .

  • 1

    在datepicker指令中选择值后,您可以使用格式化程序 . 例如

    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 .

  • 23

    已经写了这么多答案,这是我的看法 .

    使用Angular 1.5.6和ui-bootstrap 1.3.3,只需在模型上添加它即可完成 .

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

    Note :只有当您担心日期落后1天并且没有受到额外时间T00:00:00.000Z的困扰时才使用此项

    更新了Plunkr:

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

  • 13

    所有提出的解决方案都不适用于我,但最接近的解决方案来自@Rishii .

    我正在使用AngularJS 1.4.4和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;
            }
          };
        }
      };
    }])
    
  • 9

    我可以通过在JSP文件中添加以下代码来解决这个问题 . 现在模型和UI值都相同 .

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

    更改ng-model的默认日期格式的步骤

    对于不同的日期格式,请在此处检查jqueryui datepicker日期格式值,例如我使用了dd / mm / yy

    创建angularjs指令

    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');
            });
        }
     }
    });
    

    写dateFilter函数

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

    在html页面中写入ng-modal属性

    <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 />
    
  • 1

    最后我对上述问题有了很好的解决方案 . angular-strap具有与我期望的完全相同的功能 . 只需应用 date-format="MM/dd/yyyy" date-type="string" ,我得到了以给定格式更新ng-model的预期行为 .

    <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>
    

    这是工作插件link

  • 0

    定义一个解决bug的新指令并不是很理想 .

    由于日期选择器正确显示更晚的日期,因此一个简单的解决方法可能是将模型变量首先设置为null,然后在一段时间后设置为当前日期:

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

    datepicker(和datepicker-popup)指令要求ng-model是Date对象 . 记录here .

    如果您希望ng-model是特定格式的字符串,则应创建包装器指令 . 这是一个例子(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>
    
  • 5

    在检查了上面的答案之后,我想出了这个并且它完美地运行而无需在标记中添加额外的属性

    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');
                });
            }
        }
    });
    

相关问题