1. 程式人生 > >angularjs之ui-bootstrap的Datepicker Popup不使用JS實現雙日期選擇控件

angularjs之ui-bootstrap的Datepicker Popup不使用JS實現雙日期選擇控件

function 2.3 spa ots fun 自定義指令 str borde ext

最開始使用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會持續更新的。

angularjs之ui-bootstrap的Datepicker Popup不使用JS實現雙日期選擇控件