【经验】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,问题解决。解决问题的过程伴随着查资料的过程,是一步步完善的。也希望大家在遇到同样的问题时少走弯路。

另:码字不易,转载请注明出处。

 

posted @ 2016-07-12 16:51  茜瓜  阅读(17321)  评论(20编辑  收藏  举报