zoukankan      html  css  js  c++  java
  • angularjs之ui-bootstrap的Datepicker Popup不使用JS实现双日期选择控件

    最开始使用ui-bootstrap的Datepicker Popup日期选择插件实现双日期选择时间范围时,在网上搜了一些通过JS去实现的方法,不过后来发现可以不必通过JS去处理,只需要使用其自身的属性和参数即可实现,效果如下图(一截图就不显示鼠标的红色圆圈不可选的样式了。。。尴尬):

    这里先附上我觉得简单易懂的JS实现方法,大家可以看看实现的原理:

    以下代码就是最开始网上搜索的简单易懂的:http://www.cnblogs.com/tonghaolang/p/5972676.html

    <!DOCTYPE html>
    <html lang="en" ng-app="myApp">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css">  
        <script src="http://cdn.bootcss.com/angular.js/1.5.8/angular.js"></script>
        <script src="http://cdn.bootcss.com/angular-ui-bootstrap/2.2.0/ui-bootstrap-tpls.js"></script>
        <script src="https://cdn.bootcss.com/angular-i18n/1.5.8/angular-locale_zh-cn.js"></script>
        <style type="text/css">
            .uib-datepicker-popup.dropdown-menu .uib-daypicker{
                outline: none;
            }
        </style>
        <script>
            angular.module('myApp',['ui.bootstrap'])
            .controller('myCtrl',function($scope){
                
                $scope.dt1;
                $scope.dt2;
                $scope.datepickerOptions1={
                    maxDate:$scope.dt2,
                    showWeeks:false,
                    startingDay:1
                };
                $scope.datepickerOptions2={
                    minDate:$scope.dt1,
                    showWeeks:false,
                    startingDay:1
                };
                //打开popup
                $scope.pop1={
                    opened:false
                };
                $scope.pop2={
                    opened:false
                };
                $scope.openpop1=function(){
                    $scope.pop1.opened=!$scope.pop1.opened;
                };
                $scope.openpop2=function(){
                    $scope.pop2.opened=!$scope.pop2.opened;
                };
    
                //监听dt1 和dt2 如果dt1 变化就设置 datepickeroptions.mindate就变化
    
                $scope.$watch('dt1',function(newValue,oldValue){
                    $scope.datepickerOptions2.minDate=newValue;
                });
                $scope.$watch('dt2',function(newValue,oldValue){
                    $scope.datepickerOptions1.maxDate=newValue;
                });
                /*手动输入限制 使用表单验证
                *datepicker输入限制 使用maxDate minDate
                *startPopup   最小时间  没有限制 最大时间 endTime
                *endPopup 最小时间 startTime 最大时间 today
                */
            })
        </script>
    </head>
    <body ng-controller="myCtrl">
        <div class="row">
            <div class="col-xs-2">上架时间:</div>
            <div class="col-xs-4">
                <p class="input-group">
                    <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="dt1" is-open="pop1.opened" 
                         ng-required="true" close-text="关闭" clear-text="清空" current-text="今天" datepicker-options="datepickerOptions1" ng-click="openpop1()"/>
                    <span class="input-group-btn">
                        <button class="btn btn-default" ng-click="openpop1()"><i class="glyphicon  glyphicon-calendar"></i></button>
                    </span>
                </p>
            </div>
            <div class="col-xs-2">下架时间:</div>
            <div class="col-xs-4">
                <p class="input-group">
                    <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="dt2" is-open="pop2.opened" 
                         ng-required="true" close-text="关闭" clear-text="清空" current-text="今天" datepicker-options="datepickerOptions2" ng-click="openpop2()"/>
                    <span class="input-group-btn">
                        <button class="btn btn-default" ng-click="openpop2()"><i class="glyphicon  glyphicon-calendar"></i></button>
                    </span>
                </p>
            </div>
        </div>
    </body>
    </html>

     以上可以实现下架时间不能小于上架时间,上架时间不能大于下架时间。

    但是在项目里,很多页面都要使用,虽然可以定义在自定义指令里,可如果遇到后台的开始日期和结束日期两个字段和其他页面的不同,那就要加一层处理了。所以还是觉得麻烦。

    后来发现可以不用JS,使用其自身的属性和参数即可实现。下面具体说实现的具体属性:

    datepicker-options:对,就是这个属性,他里面有很多的参数,因为ui-bootstrap的Datepicker Popup是Datepicker的扩展,所以uib-datepicker-popup可以使用Datepicker的配置,也就是datepicker-options,是一个Json对象,可以设置的项有:

    默认值 备注
    customClass    一个可选的函数,设置日期面板中每个日期的样式。传入参数为一个json对象{date: obj1, mode: obj2},返回值为类的名字
    dateDisabled   一个可选的函数,设置日期面板中每个日期是否可选。传入参数为一个json对象{date: obj1, mode: obj2},返回值为bool类型
    datepickerMode day 可设置为day,month,year。表示控件的选择模式
    formatDay dd 天数的格式化形式
    formatMonth MMMM 月份的格式化形式
    formatYear yyyy 年份的格式化形式
    formatDayHeader EEE 星期的格式化形式
    formatDayTitle MMMM yyyy 按天数选择日期时,面板中当前月份和年份的格式化形式(显示为:六月 2016 的地方)
    formatMonthTitle yyyy 按月份选择日期时,面板中当前年份的格式化形式
    initDate null 初始化日期
    maxDate null 可选择的最大日期(必须是Javascript日期类型)
    maxMode year 可选择的最大日期模式
    minDate null 可选择的最小日期(必须是Javascript日期类型)
    minMode day 可选择的最小日期模式
    shortcutPropagation  false 是否禁用键盘事件传播
    showWeeks true 是否显示面板中的日期是当年的第几周
    startingDay $locale.DATETIME_FORMATS.FIRSTDAYOFWEEK 一个星期从周几开始。可设置为0到6的数字,0表示周日,6表示周六
    yearRows 4 选择年份时显示多少行
    yearColumns 5 选择年份时显示多少列

    而我们这里用到的就是minDate和maxDate两个参数;

    下面附上实现的代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
        <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
        <link href="lib/font-awesome-4.7.0/css/font-awesome.min.css">
        
        <script src="lib/angular1.6.1.js"></script>
        <script src="lib/ui-bootstrap-tpls-2.3.2.js"></script>
        <script src="lib/angular-locale_zh-cn.js"></script>
        <style>
            .container{
                margin-top: 50px;
            }
            .uib-datepicker-popup.dropdown-menu .uib-daypicker{
                outline: none;
            }
        </style>
    </head>
    <body>
        <div ng-app="myApp" ng-controller="myCtrl">
            <div class="container">
                <div class="row">
                  <div class="col-md-4">上架日期:
                    <p class="input-group">
                      <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="startTime" is-open="open1" datepicker-options="{maxDate:(endTime),showWeeks:false}" ng-required="true" clear-text="清空" current-text="今天" close-text="取消" alt-input-formats="altInputFormats" ng-click="open1=!open1"/>
                      <span class="input-group-btn">
                        <button type="button" class="btn btn-default" ng-click="open1=!open1"><i class="glyphicon glyphicon-calendar"></i></button>
                      </span>
                    </p>
                  </div>
        
                  <div class="col-md-4">下架日期:
                    <p class="input-group">
                      <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="endTime" is-open="open2" datepicker-options="{minDate:(startTime),showWeeks:false}" ng-required="true" clear-text="清空" current-text="今天" close-text="取消"  ng-click="open2=!open2"/>
                      <span class="input-group-btn">
                        <button type="button" class="btn btn-default" ng-click="open2=!open2"><i class="glyphicon glyphicon-calendar"></i></button>
                      </span>
                    </p>
                  </div>
                </div>
            </div>
        </div>
    
        <script type="text/javascript">
            angular.module('myApp',['ui.bootstrap'])
            .controller('myCtrl',function ($scope) {
                 
            })
        </script>
    </body>
    </html>

    对,正如你所见。。。完全不用在JS里写任何代码来控制,只需要设置datepicker-options="{maxDate:(endTime),showWeeks:false}"和datepicker-options="{minDate:(endTime),showWeeks:false}"里面的showWeeks:false是表示不显示周数,可以看上面的具体参数介绍。

    下面说一下具体实现的原理:

    <div class="col-md-4">上架日期:
    <p class="input-group">
      <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="startTime" is-open="open1" datepicker-options="{maxDate:(endTime),showWeeks:false}" ng-required="true" clear-text="清空" current-text="今天" close-text="取消" alt-input-formats="altInputFormats" ng-click="open1=!open1"/>
      <span class="input-group-btn">
        <button type="button" class="btn btn-default" ng-click="open1=!open1"><i class="glyphicon glyphicon-calendar"></i></button>
      </span>
    </p>
    </div>
    
    <div class="col-md-4">下架日期:
    <p class="input-group">
      <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="endTime" is-open="open2" datepicker-options="{minDate:(startTime),showWeeks:false}" ng-required="true" clear-text="清空" current-text="今天" close-text="取消"  ng-click="open2=!open2"/>
      <span class="input-group-btn">
        <button type="button" class="btn btn-default" ng-click="open2=!open2"><i class="glyphicon glyphicon-calendar"></i></button>
      </span>
    </p>
    </div>
    <input type="text" class="form-control" uib-datepicker-popup="yyyy-MM-dd" ng-model="startTime" is-open="open1" datepicker-options="{maxDate:(endTime),showWeeks:false}" 
    ng-required="true" clear-text="清空" current-text="今天" close-text="取消" alt-input-formats="altInputFormats" ng-click="open1=!open1"/>
    1. uib-datepicker-popup="yyyy-MM-dd": 就是设置其日期显示的格式了,这个属性是必须有的,值默认就是yy-MM-dd,不然插件就不能用了哈,下面会附上uib-datepicker-popup的所有参数介绍。
    2. ng-model="startTime": 这就是绑定的开始日期,有输入其startTime就会改变,你知道的。。。
    3. is-open="open1": is-open为true时,会显示日期选择界面,为false则隐藏,后面是通过ng-click来改变这个open1的,可以看后面。
    4. datepicker-options="{maxDate:(endTime),showWeeks:false}": 这就是说的关键了,里面的maxDate就是可以选择的最大日期了,如果是minDate的话,就是能选择的最小日期,你懂的。。。后面的showWeeks控制是否显示周数。
    5. clear-text="清空" current-text="今天" close-text="取消": 你引用了angular-locale_zh-cn.js的话,这里设置了,原来的today、clear和close就会变成你设置的中文了。
    6. ng-click="open1=!open1": 这里就是前面说的,控制is-open的true和false了,最开始angular里是没有定义open1的,所以自然是false了,当我们点击后,给open1赋值为!open1,open1就是true了,
    我这么理解的,具体正确不,就不知道了。。。

    所以当你第一个日期选择了后,第二个日期的minDate就已经设置好了,是不能选择比它小的日期的,相反,如果你第二个日期也选择好了,那么第一个日期的maxDate就已经设置好了,所以第一个日期就不能大于第二个日期了。
    第一个的maxDate参数的值就是第二个日期选择的时间,第二个日期的minDate参数的值就是第一个日期选择的时间,这样应该能理解了吧。。。

    上面说到了uib-datepicker-popup,它支持多种格式化方式
    这里就不多说了,具体可以看pilixiami博主的http://www.cnblogs.com/pilixiami/p/5611346.html

    对了,之前在项目里遇到了通过该插件获取的时间传给后台查询数据,会出现日期有差别,应该是时区的原因,所以大家要注意了,这里选择的日期是一个对象,你可以输出看看,
    传到后台的时候,最后面的一个字母Z就是影响时区的了,网上有说将其换成UTC的,因为我们当时后台接收的是字符串如:2017-08-08,所以我在JS里使用的过滤器$filter('date')($scope.startTime, 'yyyy-MM-dd')
    将选择的时间转换为字符串2017-08-08的格式,所以,那个时区就没具体的去研究处理了

    好了,上面的可以在任意页面使用了,而且不用在JS里做任何处理哦。。。后面发现有BUG会持续更新的。
  • 相关阅读:
    2017ecjtu-summer training # 9 HDU 4544
    2017ecjtu-summer training #6 Gym 100952D
    HDU 1241 DFS
    集训队选拔赛 day4
    Educational Codeforces Round 67 (Rated for Div. 2)
    Codeforces Round #566 (Div. 2)
    Codeforces Round #567 (Div. 2)
    Codeforces Round #568 (Div. 2)
    Codeforces Round #569 (Div. 2)
    牛客练习赛48
  • 原文地址:https://www.cnblogs.com/amor17/p/7588043.html
Copyright © 2011-2022 走看看