【經驗】Angularjs 中使用 layDate 日期控件


layDate 控件地址:http://laydate.layui.com/

前情:原來系統中使用的日期控件是UI bootstrap(地址:https://angular-ui.github.io/bootstrap/)里的。后來因為各種原因,要換掉UI bootstrap中的日期控件,改用layDate日期控件。

解決思路:將layDate的初始化及相關代碼定義在指令里。

問題關鍵點:layDate操作的是Html元素的,怎么實現雙向綁定,同步Angularjs模板值和Html的元素值。

指令具體代碼:

 1     /**
 2          * 使用示例
 3          * <input def-laydate type="text" id="id1" ng-model="startTime"/>
 4          */
 5         app
 6         .directive('defLaydate', function() {
 7             return {
 8                 require: '?ngModel',
 9                 restrict: 'A',
10                 scope: {
11                     ngModel: '='
14                 },
15                 link: function(scope, element, attr, ngModel) {
16                     var _date = null,_config={};
17                     
18                         // 初始化參數 
19                     _config = {
20                         elem: '#' + attr.id,
21                         format: attr.format != undefined && attr.format != '' ? attr.format : 'YYYY-MM-DD',
22                         max:attr.hasOwnProperty('maxDate')?attr.maxDate:'',
23                         min:attr.hasOwnProperty('minDate')?attr.minDate:'',
24                         choose: function(data) {
25                             scope.$apply(setViewValue);
26                             
27                         },
28                         clear:function(){
29                            ngModel.$setViewValue(null);
30                         }
31                     };
32                     // 初始化
33                     _date= laydate(_config);
34 
35                   
36                    
37                     // 模型值同步到視圖上
38                     ngModel.$render = function() {
39                         element.val(ngModel.$viewValue || '');
40                     };
41 
42                     // 監聽元素上的事件
43                     element.on('blur keyup change', function() {
44                         scope.$apply(setViewValue);
45                     });
46 
47                     setViewValue();
48 
49                     // 更新模型上的視圖值
50                     function setViewValue() {
51                         var val = element.val();
52                         ngModel.$setViewValue(val);
53                     }
54                 }  
55             }
56         })

---以上代碼使用示例為 <input def-laydate type="text" id="id1" ng-model="startTime"/> 

注意:1.指令只能用做元素屬性。2.元素必須要有唯一id屬性。

 

到此為止,在Angularjs里使用laydate的基本目標實現了。但是,日期組件難免會有日期選擇范圍限制的要求,比如日期可選的最大值,最小值。現對指令做優化以滿足要求:

 1 app
 2         .directive('defLaydate', function() {
 3             return {
 4                 require: '?ngModel',
 5                 restrict: 'A',
 6                 scope: {
 7                     ngModel: '=',
 8                     maxDate:'@',
 9                     minDate:'@'
10                 },
11                 link: function(scope, element, attr, ngModel) {
12                     var _date = null,_config={};
13                     
14                         // 初始化參數 
15                     _config = {
16                         elem: '#' + attr.id,
17                         format: attr.format != undefined && attr.format != '' ? attr.format : 'YYYY-MM-DD',
18                         max:attr.hasOwnProperty('maxDate')?attr.maxDate:'',
19                         min:attr.hasOwnProperty('minDate')?attr.minDate:'',
20                         choose: function(data) {
21                             scope.$apply(setViewValue);
22                             
23                         },
24                         clear:function(){
25                            ngModel.$setViewValue(null);
26                         }
27                     };
28                     // 初始化
29                     _date= laydate(_config);
30                     
31                     // 監聽日期最大值
32                     if(attr.hasOwnProperty('maxDate')){
33                         attr.$observe('maxDate', function (val) {
34                             _config.max = val;
35                         })
36                     }
37                     // 監聽日期最小值
38                     if(attr.hasOwnProperty('minDate')){
39                        attr.$observe('minDate', function (val) {
40                             _config.min = val;
41                         })
42                     }
43                    
44                     // 模型值同步到視圖上
45                     ngModel.$render = function() {
46                         element.val(ngModel.$viewValue || '');
47                     };
48 
49                     // 監聽元素上的事件
50                     element.on('blur keyup change', function() {
51                         scope.$apply(setViewValue);
52                     });
53 
54                     setViewValue();
55 
56                     // 更新模型上的視圖值
57                     function setViewValue() {
58                         var val = element.val();
59                         ngModel.$setViewValue(val);
60                     }
61                 }  
62             }
63         })

 

 ---以上代碼使用示例為 <input def-laydate type="text" id="id1" ng-model="startTime"  max-date="{{model.max}}" min-date="{{model.min}}"/> min-date,max-date屬性按需添加。

 

這樣的指令一般情況下已經可以滿足使用,但是在結合ngDialog使用時出現了問題:layDate在初始化中getElementById 獲取元素時,彈窗中的html內容還沒有持到頁面的結點樹中,故而報錯。

於是希望指令的link代碼可以在彈窗渲染后再執行,查找資料后,在指令中引入了$timeout:

app.directive('ngcLayDate', function($timeout) {
            return {
                require: '?ngModel',
                restrict: 'A',
                scope: {
                    ngModel: '=',
                    maxDate:'@',
                    minDate:'@'
                },
                link: function(scope, element, attr, ngModel) {
                    var _date = null,_config={};
                     // 渲染模板完成后執行
                    $timeout(function(){ 
                        // 初始化參數 
                        _config = {
                            elem: '#' + attr.id,
                            format: attr.format != undefined && attr.format != '' ? attr.format : 'YYYY-MM-DD',
                            max:attr.hasOwnProperty('maxDate')?attr.maxDate:'',
                            min:attr.hasOwnProperty('minDate')?attr.minDate:'',
                            choose: function(data) {
                                scope.$apply(setViewValue);
                                
                            },
                            clear:function(){
                               ngModel.$setViewValue(null);
                            }
                        };
                        // 初始化
                        _date= laydate(_config);

                        // 監聽日期最大值
                        if(attr.hasOwnProperty('maxDate')){
                            attr.$observe('maxDate', function (val) {
                                _config.max = val;
                            })
                        }
                        // 監聽日期最小值
                        if(attr.hasOwnProperty('minDate')){
                           attr.$observe('minDate', function (val) {
                                _config.min = val;
                            })
                        }
                       
                        // 模型值同步到視圖上
                        ngModel.$render = function() {
                            element.val(ngModel.$viewValue || '');
                        };

                        // 監聽元素上的事件
                        element.on('blur keyup change', function() {
                            scope.$apply(setViewValue);
                        });

                        setViewValue();

                        // 更新模型上的視圖值
                        function setViewValue() {
                            var val = element.val();
                            ngModel.$setViewValue(val);
                        }
                    },0);  
                }
            };
        })

 

OK,問題解決。解決問題的過程伴隨着查資料的過程,是一步步完善的。也希望大家在遇到同樣的問題時少走彎路。

另:碼字不易,轉載請注明出處。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM