当值最初在范围内设置时,日期选择器弹出格式不起作用

Posted

技术标签:

【中文标题】当值最初在范围内设置时,日期选择器弹出格式不起作用【英文标题】:Datepicker-popup formatting not working when value set initially in scope 【发布时间】:2016-12-04 00:49:18 【问题描述】:

我在 Plunker (http://plnkr.co/edit/053VJYm1MpZUiKwFTfrT?p=preview) 上使用这个自定义指令使用 Angular UI 引导日期选择器弹出窗口:

//Module
var userModule = angular.module("userModule",['ui.bootstrap']);

//Controller
userModule.controller("sampleController", ['$scope', function ($scope) 
    $scope.minDate = new Date();
]);

//Directive code
userModule.directive('datePicker', [function (dateFilter) 
    return 
        restrict: 'E',
        require: 'ngModel',
        scope: 
            ngModel: '=',
            ngReadonly: '=?',
            minDate: '=?',
            maxDate: '=?',
            dtpRequired: '=?',
            dateOptions: '=?'
        ,
        template: '<p class="input-group">' +
                    '<input type="text" style="cursor:pointer" class="form-control" datepicker-popup="format"' +
                        'ng-model="ngModel" is-open="opened"' +
                            'min-date="minDate" max-date="maxDate"' +
                                'datepicker-options="dateOptions" date-disabled="disabled(date, mode)"' +
                                 'ng-required="dtpRequired" close-text="Close" ng-readonly="ngReadonly" ng-click="openPopup()" />' +
                         '<span class="input-group-btn">' +
                            '<button type="button" class="btn btn-default" ng-click="openPopup($event)">' +
                                '<i class="fa fa-calendar"></i></button>' +
                        '</span>' +
                    '</p>',
        controller: function ($scope) 
            // check if it was defined.  If not - set a default
            $scope.dateOptions = $scope.dateOptions || 
                formatYear: 'yy',
                startingDay: 1,
                showWeeks: false
            ;

            $scope.openPopup = function ($event) 
                if ($event !== undefined) 
                    $event.stopPropagation();
                
                $scope.opened = true;
            ;

            $scope.format = 'dd MMMM yyyy';
        ,
        link: function ($scope, element, attrs, controller) 
            //remove the default formatter from the input directive to prevent conflict
            controller.$formatters.shift();
        
    ;
]);

这工作正常,当从日历弹出窗口中选择日期时,日期的格式也很好。但是,如果我在控制器中设置 ng-model 的日期,则日期不会格式化为“dd MMMM yyyy”,而是作为日期字符串返回,例如 Sat Oct 01 2016 01:00:00 GMT+0100 (GMT Daylight时间)。但是在 Plunker 中,我可以在控制器中设置一个日期,并且它的格式很好。 这是日期选择器的 html

<date-picker ng-model="startDate.value" datepicker-options="dateOptions" min-date="minDate" ng-readonly="true"></date-picker>

在我的控制器startDate.value = new Date();

我不确定问题可能出在哪里。下图显示了我返回的内容。

【问题讨论】:

不能像你说的那样在 Plunker 中重现这个 - 在 sampleController 中,设置 $scope.dtpValue1 = new Date(); 并且格式显示正确(“2016 年 8 月 1 日”)。您是否在本地尝试完全相同相同的代码并遇到此问题? 是的,在我的项目中使用相同的代码给了我这个问题 这很奇怪。您是否使用相同版本的库和浏览器? 是的,相同的引导和角度版本并使用 chrome 我已经在本地(不是在 Plunker 上)尝试过,但仍然得到正确的格式。您使用的是哪个版本的 Chrome? 【参考方案1】:

我在本地尝试了您的代码,它似乎运行良好,没有任何问题。 我尝试了各种更改日期的方法,一切正常。 plnkr 中的示例与您发布的示例之间似乎有一点区别,特别是您引用日期的方式(您说您正在使用 startDate.value = new Date(); ,但在 plnkr 我看到 ng-model="dtpValue1" 。这让我觉得你还缺少其他东西,我建议在一个可在本地测试的 .zip 文件中制作一个完整的示例. 此外,由于有可能没有人能够再次重现它,因此您拥有的所有 chrome 扩展和操作系统的列表将很有用,最重要的是您应该尝试在其他机器上重现它并报告结果.

通常,在我测试过的每台机器上都可以正常工作,但我看不出它不能正常工作的充分理由。

如果我能够重现该问题,我可以设置断点并弄清楚到底发生了什么,但目前这是不可能的,我们应该专注于如何重现问题。

提供的信息似乎不足以解决此问题。

【讨论】:

【参考方案2】:

这是因为引导 UI 日期选择器实际上与字符串一起工作,并且您试图将 javascript 日期对象分配给 UI 引导在角度控制器上工作的变量。它们是不同类型的数据,因此会导致错误。如果您尝试控制变量的类型,请在从 datepicker 弹出窗口中选择一个日期之后。你会看到它是一个字符串。所以.. 如果您想从控制器设置日期,只需将其设置为字符串,而不是 javascript 对象。

【讨论】:

是的,但是引导 UI 日期选择器不应该处理 JS 日期对象的格式吗? 相信我,这是一个巨大的头痛。我尝试了很多事情来做到这一点,但做不到。它无法处理日期对象。【参考方案3】:

终于找到了解决办法。我从 Angular-UI-Bootstrap 更改为 uib-datepicker 指令,它现在在控制器中设置日期时正确格式化日期!这是我的指令中的 HTML 模板供参考:

template: '<p class="input-group">' +
            '<input type="text" style="cursor:pointer" class="form-control" uib-datepicker-popup="format"' +
                'ng-model="ngModel" is-open="opened"' +
                    'min-date="minDate" max-date="maxDate"' +
                        'datepicker-options="dateOptions"date-disabled="disabled(date, mode)"' +
                         'ng-required="dtpRequired" close-text="Close" ng-readonly="ngReadonly" ng-click="openPopup()" />' +
                 '<span class="input-group-btn">' +
                    '<button type="button" class="btn btn-default" ng-click="openPopup($event)">' +
                        '<i class="fa fa-calendar"></i></button>' +
                '</span>' +
            '</p>'

【讨论】:

【参考方案4】:

我编写了这个指令来将 string 表单服务器转换为 uib-datepicker-popup 需要的有效 javascript 格式:

app.directive('datepickerLocaleDate', ["$rootScope", "$filter", function ($rootScope, $filter) 
   return 
      restrict: 'A',
      require: 'ngModel',
      link: function (scope, element, attrs, ngModel) 

         if (ngModel) 

           // convert string to valid javascript fprmat 
            setTimeout(() => 
               ngModel.$setViewValue(new Date(ngModel['$viewValue']));
            , 3000);


            ngModel.$parsers.push(function (value) 
              return new Date(value);
            );

            ngModel.$formatters.push(function (value) 
              return value ? $filter('date')(value, 'yyyy/MM/dd') : null;
            );

         
      
   ;
]);

【讨论】:

以上是关于当值最初在范围内设置时,日期选择器弹出格式不起作用的主要内容,如果未能解决你的问题,请参考以下文章

XCUITest 如何关闭日期选择器弹出框

Datepicker:单击按钮时如何弹出日期选择器并将值存储在变量中[关闭]

当值设置为超过最大日期时,Kendo Datepicker 显示错误的格式

如何使项目角夹在微调器弹出窗口内?

.NET WinForms 的月份选择器 [重复]

带有uidatepicker委托的uipopover不起作用