如果在第二次单击时未选择日期并出现日期验证问题,则日期选择器会从日期选择器文本框中清除所选值

Posted

技术标签:

【中文标题】如果在第二次单击时未选择日期并出现日期验证问题,则日期选择器会从日期选择器文本框中清除所选值【英文标题】:Date Picker clears the selected value from date picker text box if a date is not selected on second click and issue with validation of date 【发布时间】:2017-03-02 00:13:33 【问题描述】:

我已经在我的 Angular 应用程序中实现了一个带有验证的日期选择器。

html

<div class="control-group">
                <label class="control-label" for="reservation.reservedFrom">Reserved From<sup>*</sup></label>
                <div class="controls input-group date" data-provide="datepicker">
                    <!--<input type="text" class="span4" style="width:150px" name="reservedFrom" placeholder="Reserved From" ng-model="reservation.reservedFrom"  ng-change='checkErr()'
                           validator="required" required-error-message="Date is required"  id="startDate122" />-->
                    <input class="form-control" type="text" name="startDate" core-date-picker ng-model="reservation.reservedFrom" >
                    <div class="input-group-addon">
                        <span class="glyphicon glyphicon-th"></span>
                    </div>

                    <span style="color:red">errMessageFrom</span>

                </div> <!-- /controls -->
            </div> <!-- /control-group -->
            <div class="control-group">
                <label class="control-label" for="reservation.reservedTill">Reserved Till<sup>*</sup></label>
                <div class="controls input-group date" data-provide="datepicker">
                    <!--<input type="text" style="width:150px" class="span4" name="reservedTill" placeholder="Reserved Till" data-ng-model="reservation.reservedTill"
                           validator="required" required-error-message="Date is required" valid-method="watch" id="endDate" ng-change='checkErr()' />-->
                    <input class="form-control" type="text" name="EndDate" core-date-picker ng-model="reservation.reservedTill"  ng-change='checkErr()' id="endDate1">
                    <div class="input-group-addon">
                        <span class="glyphicon glyphicon-th"></span>
                    </div>
                    <span  style="color:red">errMessageTo</span>

                </div> <!-- /controls -->
            </div> <!-- /control-group -->

控制器:

myApp.controller('editReservationController', ['$scope', '$filter', 'reservationResolved', 'pocResolved', 'accountResolved', 'reservationServices', '$location', '$state',
    function ($scope, $filter, reservationResolved, pocResolved, accountResolved, reservationServices, $location, $state) 
        $scope.reservation = new Object();
        $scope.accounts = accountResolved.data;
        $scope.pocs = pocResolved.data;
        $scope.reservation.employee = reservationResolved.data;





        $scope.updateReservation = function () 
            var from = $scope.reservation.reservedFrom;
            var till = $scope.reservation.reservedTill;
            if ($scope.editReservationForm.$valid && $scope.checkErr()) 

                var from = $scope.reservation.reservedFrom;
                var till = $scope.reservation.reservedTill;

                //var t = $scope.checkErr();

                //TODO: fix it properly
                $scope.reservation.reservedTill = '';
                $scope.reservation.reservedFrom = '';

                $scope.reservation.reservedFrom = $('#startDate').val();
                $scope.reservation.reservedTill = $('#endDate').val();

               reservationServices.updateReservation($scope.reservation).then(function (result) 
                        $scope.data = result.data;
                        if (!result.data.error) 
                            $state.transitionTo('employeeTalentPool', 
                                id: $state.params.id
                            );
                        
                    );   
            
        ;
        $scope.cancel = function () 
            $location.path("/reservations");
        ;

        $scope.$watch("reservation.reservedFrom", function (newValue, oldValue) 
            $scope.checkErr();

        );


        $scope.$watch("reservation.reservedTill", function (newValue, oldValue) 
            $scope.checkErr();

        );
        $scope.getCurrentDate =  function() 
            var utcDate = new Date();
            var isoExtendedDate = utcDate.toISOString();
            var isoSimpleDate = isoExtendedDate.split("T")[0];
            return isoSimpleDate;
        
        $scope.checkErr = function () 

            var startDateStr = $scope.reservation.reservedFrom;
            var endDateStr = $scope.reservation.reservedTill;

            var startDate;
            if (startDateStr != undefined) 
                startDate = new Date(startDateStr);
            

            var endDate;
            if (endDateStr != undefined) 
                endDate = new Date(endDateStr);
            
            $scope.errMessageFrom = '';
            $scope.errMessageTo = '';

            var myDate = new Date(); // Set this to your date in whichever timezone.
            var utcDate = myDate.toUTCString();




            if (startDate != undefined && startDate < new Date()) 
                $scope.errMessageFrom = 'Start Date should be greater than or equal to present day.';
                return false;
            
            if (endDate != undefined && new Date(endDate) < new Date()) 
                $scope.errMessageTo = 'End Date should be greater than or equal to present day.';
                return false;
            
            if (startDate != undefined && endDate != undefined  && endDate <= startDate) 
                $scope.errMessageTo = "End date must be after start day.";
                return false;
            
            return true;
        ;
    ]);

App.js:

//Date Picker
myApp.directive('coreDatePicker', function ($compile) 
    return 
        restrict: 'A',
        require: 'ngModel',
        compile: function (element, attrs) 
            $(element[0]).datepicker(
                autoclose: true,
                format: "dd/mm/yyyy"
            );

            return this.link;
        ,
        link: function (scope, element, attrs, ngModelCtrl) 
            $(element[0]).datepicker().on("change", function (e) 
                scope.$apply(function () 
                    ngModelCtrl.$setViewValue(element.val());
                );
            );
        
    ;
);

我将解释我正在谈论的场景。

问题 1 - 我从日历中选择了一个日期,它在日期选择器文本框中正确显示。然后我再次单击日期选择器以选择不同的日期,但后来我决定不更改当前选择的日期,因此我在日历之外单击了第二次而没有选择日期。由于我第二次没有选择日期,因此日期选择器从文本框中清除了第一次选择的日期,使其为空。我不希望这种情况发生。我希望第一个选择的日期保留在那里,除非选择了不同的日期(不是空值)。

问题 2 - 在验证日期时,我无法将所选日期与当前日期进行比较。如果所选日期小于当前日期,则应显示错误消息。但就我而言,如果我选择与今天相同的日期,则会显示错误。它应该允许我选择当天。

我使用过 Bootstrap-datepicker。如果需要更多信息,请告诉我。

提前致谢。

【问题讨论】:

Fiddle 或 Plunkr 会很有帮助。 我不知道如何通过链接控制器和指令等来创建 Plunkr 或 Fiddle...抱歉 core-date-picker 这是你的 datepicker 自定义指令吗?我没有在您的代码中看到您正在使用 UI-bootstrap datepicker。 我正在使用引导日期选择器。不确定与 UI Bootstrap datepicker 有什么区别。我得到了这个应用程序。你认为我应该改用 UI 日期选择器吗?我尝试从 html 标记中删除 'core-date-picker' 并且验证变得无效 【参考方案1】:

我一眼就注意到了,

 link: function (scope, element, attrs, ngModelCtrl) 
            $(element[0]).datepicker().on("change", function (e) 
                scope.$apply(function () 
                    ngModelCtrl.$setViewValue(element.val());
                );
            );
        

应该开火吗?我从 问题 1 了解到的是,无论是否有变化,它都会触发。你有没有想过在

尝试一些检查
$(element[0]).datepicker().on("change", function (e) 
                    scope.$apply(function () 
                        ngModelCtrl.$setViewValue(element.val());
                    );
                );

试试

$(element[0]).datepicker().on("change", function (e) 
                    scope.$apply(function () 
                        if(element.val()) 
                          ngModelCtrl.$setViewValue(element.val());
                       
                    );
                );

只需在 element.val() 上稍作检查,尝试一下不会有任何害处。

对于第二期,我认为你不能这样比较日期。

new Date()

返回

2016 年 10 月 20 日星期四 14:54:17 GMT+0800(马来半岛标准时间)

你的startDateStr是什么

注意到new Date() 有几秒和几毫秒。

如果您只想比较 (DD/MM/yyyy) 的日期、月份和年份,我建议您先转换日期,然后再进行比较。

或者像单独比较

startDate.getDate() < new Date().getDate() // To compare a day 

为了更好的选择,我建议moment。 Github.

var startDate = moment(startDateStr, 'MM-DD-YYYY').format('MMMM D');

var today = moment().format('D MMM, YYYY');
if (startDate != undefined && startDate < today) 


更新

您是否尝试过将检查移至

 $scope.$watch("reservation.reservedFrom", function (newValue, oldValue) 
         if(newValue && newValue !==  oldValue) 
             $scope.checkErr();
         

        );


        $scope.$watch("reservation.reservedTill", function (newValue, oldValue) 
            if(newValue && newValue !==  oldValue) 
               $scope.checkErr();
            

        );

当你使用 = 比较两个日期对象时,它们是通过 valueOf 进行比较,这与日期的 getTime 相同。

但是当你使用==的时候,它们是同类型的两个不同对象,所以返回false。

所以在你的情况下^比较两个日期。正确的做法是

 var startDate = moment(startDateStr, 'MM-DD-YYYY').format('MMMM D');

    var today = moment().format('D MMM, YYYY');
    if (startDate != undefined && startDate.getTime() < today.getTime()) 

    

这些解释取自Here。您可以查看链接以获取更多说明。

getTime 将日期转换为一个纪元等价物,它基本上是可以被计算的数字/数字值。 new Date() 是一个对象,new Date('10/20/2016') 也是一个对象,并且对象 A 不能等于对象 b。要进一步了解这一点,您可以在浏览器控制台上尝试。

new Date() === new Date();
> false

但是

new Date().getTime() === new Date().getTime()
>true;

第一个是假是假的,因为你在比较两个对象。第二个相当于与数值进行比较。毕竟

new Date().getTime()
>1477011127232

【讨论】:

请查看附件截图:它将显示我的日期格式。 s10.postimg.org/a9m9cjuqx/screenshot.jpg 我也试过 scope.$apply(function () if (element.val()) ngModelCtrl.$setViewValue(element.val()); 它没有任何区别。 @Phoenix 就像我说的,你的屏幕截图也很清楚。 startDateStr10/21/2016 并且您使用 new Date(startDate) 创建 startDate 。因此 startDate 不会有 Hours:Minute 和 seconds 。这就是为什么 startDate 的 HH:MM:SS00:00:00。但是,new Date() 将创建带有小时、分钟和秒的当前日期。 startDate 和 new Date() 无法比较,除非您从 new Date() 中取出秒、分钟和小时 好的,我会按照您的建议使用 moment 进行验证。第二次点击后清除日期怎么样? 还是一样:( s12.postimg.org/awc8jhvsd/screenshot.jpg请看截图。

以上是关于如果在第二次单击时未选择日期并出现日期验证问题,则日期选择器会从日期选择器文本框中清除所选值的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 日期选择器仅在第二次点击时打开

内联日期选择器在第二次尝试时崩溃

带有TextChanged事件的文本框不会在第二次输入中显示日期

JQUERY Datepicker - 从 datepicker 选择日期后验证错误不会消失

如何使用引导模式更新引导日期时间选择器中的默认日期

选择日期后 JS 验证报告为空