如何创建一个AngularJS指令,该指令将显示我的数据是否正在加载或获取?

时间:2013-11-24 16:19:40

标签: angularjs

如果正在加载或获取数据,我的应用程序会将$ scope.loading或$ scope.fetching的值设置为大于零。

我有以下用HTML编码的内容:

<div class="activity-mask" 
     data-ng-show="creating!=0">
     <span>Creating...</span>
</div>
<div class="activity-mask" 
     data-ng-show="loading!=0">
     <span>Loading...</span>
</div>
<div class="activity-mask" 
     data-ng-show="fetching!=0">
     <span>Fetching...</span>
</div>

我在我的应用程序中的许多地方编码了这些。可以/我应该在指令中对此进行编码吗?我所拥有的工作相当不错,但任何人都能提出更好的建议吗?

2 个答案:

答案 0 :(得分:3)

我更喜欢使用事件来宣布状态变化。使用模型属性要求您始终在指令和该模型之间的范围树中具有明确的继承线。哪个可能正常。但事件系统更灵活,允许您的组件独立于假设的上下文运行。如果您决定将数据加载器移动到无法直接访问本地$ scope的服务,会发生什么?或者在控制器中触发数据加载,其范围不会从加载器模式的树的同一分支继承?拯救事件。

您对装载程序的指令可能改为:

angular.module('myApp')
    .directive('ng-loading', function () {
        return {
            template: <template string>,
            link: function (scope, element, attrs) {
                scope.loadCount = 0;
                scope.$on('loadingData', function() {
                    if (scope.loadCount === 0) {
                        element.addClass('visibleLoader');
                    }
                    scope.loadCount++;
                })
                scope.$on('loadComplete', function() {
                    if (scope.loadCount > 0) {
                        scope.loadCount--;
                        if (scope.loadCount === 0) {
                            element.removeClass('visibleLoader');
                        }
                    }
                })
            }
        }
    };
})

然后,只需使用您加载数据的任何控制器或服务中的$rootScope.broadcast('loadingData')。并在数据加载完成时使用promise模式触发close事件:

$http.get('/urlToFetch').then(function(){$rootScope.broadcast('loadComplete')});

加载器是一种非常简单的模式,通常可以管理继承问题。 (或者,您甚至可以将它全部放到$ rootScope上。)因此,如果适合您,请随意使用模型属性。但是,习惯于事件驱动的系统可以让您更灵活地重复使用您的指令,无论您喜欢什么。此外,您可以拥有一系列相关行为,这些行为都可以关闭单个事件广播,而无需其他任何事情。

答案 1 :(得分:1)

指令代码

angular.module('myApp')
.directive('ng-loading', function () {
    return {
        restrict: 'A',
        template: [
            '<div class="activity-mask">',
            '<span>Loading ...</span>',          
            '</div>'
        ].join(''),
        link: function (scope, element, attrs) {
            var promiseObj = scope['loading'] || scope['fetching'];
            if (promiseObj && angular.isFunction(promiseObj['finally']) ) {
                promiseObj['finally'](function() {
                  element.addClass('ng-hide'); //hide directive
                });
            }
        }
    };
})

查看代码

<div ng-loading></div>

控制器代码

$scope.fetching = $http.get('/urlToFetch').then(function(){ /* your code */});