Javascript Angularjs:如何在 $routeProvider 中使用“解决”时显示加载图标?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12352411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 07:47:36  来源:igfitidea点击:

Angularjs: How to display loading-icon when using 'resolve' in $routeProvider?

javascriptangularjs

提问by Roar Skullestad

The following code reads via a service and shows on the web page a list of 'page' objects for a specific 'page category' (string). Using the resolve object property in $routeProvider.when(), I am able to postpone updating the view until the new value is ready.

以下代码通过服务读取并在网页上显示特定“页面类别”(字符串)的“页面”对象列表。使用 $routeProvider.when() 中的解析对象属性,我可以推迟更新视图,直到新值准备就绪。

Two questions:

两个问题:

  1. When asking for a new page list, I want to show a loading-icon. How can I detect (in a non-hackish way) the event when the reading from server starts (and the loading-icon should be displayed)? I guess I could do something like $('.pages-loading-icon').show() in the service, but find that to be too gui dependent too placed in the service.

  2. When the new value is ready, I would like the old to fade out and the new to fade in. What is the 'angular' way to do this? I have tried to do it in the controller using $watch, but that causes the new value to be display shortly before the fadeout starts.

  1. 当要求一个新的页面列表时,我想显示一个加载图标。当从服务器开始读取(并且应该显示加载图标)时,如何检测(以非黑客的方式)事件?我想我可以在服务中做类似 $('.pages-loading-icon').show() 的事情,但发现它太依赖于 gui 太放在服务中了。

  2. 当新值准备好时,我希望旧值淡出,新值淡入。这样做的“角度”方式是什么?我曾尝试使用 $watch 在控制器中执行此操作,但这会导致在淡出开始前不久显示新值。

The code:

编码:

app.js:

应用程序.js:

$routeProvider.when('/:cat', { templateUrl: 'partials/view.html', controller: RouteCtrl, resolve: RouteCtrl.resolve});

controllers.js:

控制器.js:

function RouteCtrl($scope, $routeParams, pages) {
        $scope.params = $routeParams;
        $scope.pages = pages;
    }

RouteCtrl.resolve={
    pages: function($routeParams, Pages){
        if($routeParams.hasOwnProperty('cat')){
            return Pages.query($routeParams.cat);
        }
    }
}

services.js:The last pages read is stored in currentPages and its category in lastCat.

services.js:最后读取的页面存储在 currentPages 中,其类别存储在 lastCat 中。

factory('Pages', function($resource, $q, $timeout){
    return {
        res: $resource('jsonService/cat=:cat', {}, {
            query: {method:'GET', params:{cat:'cat'}, isArray:true}
        }),
        lastCat: null,
        currentPages: null,
        query: function(cat) {
            var res = this.res;
            if(cat != this.lastCat){
                var deferred = $q.defer();
                var p = res.query({'cat':cat}, function(){
                    deferred.resolve(p);
                });
                this.lastCat = cat;
                this.currentPages = deferred.promise;
            }
            return this.currentPages;
        }
    };
})

view.html

视图.html

<ul >
    <li ng-repeat="page in pages">
        <a href="#{{params.cat}}/{{page.slug}}">{{page.title}}</a>
    </li>
</ul>

回答by Tosh

Not exactly sure whether this would work in your code as you have $resource integration. But it may be worth to look into angular events: $routeChangeStartand $routeChangeSuccess.

不确定这是否适用于您的代码,因为您有 $resource 集成。但可能值得研究角度事件:$routeChangeStart$routeChangeSuccess.

in html:

在 HTML 中:

<span ng-show="isViewLoading"> loading the view... </span>

in controller (which defines the scope of the html above):

在控制器中(它定义了上面 html 的范围):

$scope.isViewLoading = false;
$scope.$on('$routeChangeStart', function() {
  $scope.isViewLoading = true;
});
$scope.$on('$routeChangeSuccess', function() {
  $scope.isViewLoading = false;
});
$scope.$on('$routeChangeError', function() {
  $scope.isViewLoading = false;
});

回答by Tiago Rold?o

The routing system for angular seems to be a bit limited..

This solved it for me:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm

angular 的路由系统似乎有点受限..

这为我解决了:http:
//www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side -Events.htm

Also, about the events triggering twice: if you setup a route do map to "a/b/c" angular automatically sets up another route, "a/b/c/" (with trailing slash) to redirect to the first (and vice versa), and both trigger events. I just test for a presence of route parameters.

另外,关于触发两次的事件:如果您设置了一条路线,则映射到“a/b/c”角度会自动设置另一条路线,“a/b/c/”(带有斜杠)重定向到第一个(和反之亦然),并且都触发事件。我只是测试路由参数的存在。

Regarding the limited condition of the routing sistem: there is this pullfrom angular, to extend it's capabilities.

关于路由系统的有限条件:有来自 angular 的这种拉力,以扩展它的功能。

回答by Edwin Beltran

I like the 'ng-show'... But the 'ui-if'of the Angular UI project is better IMHO.. Since remove the HTML code from the DOM...

我喜欢'ng-show'......但'ui-if'Angular UI 项目的更好恕我直言.. 因为从 DOM 中删除 HTML 代码......

<span ui-if = "isViewLoading"> loading the view... </span>

_e

_e

回答by user1126545

You can also use the ng-show directive. Simply check whether you model is empty and display a DOM subset like so:

您还可以使用 ng-show 指令。只需检查您的模型是否为空并显示一个 DOM 子集,如下所示:

    <!-- model not ready -->
    <div style="width: 200" ng-show="lines == ''">
      <div class="progress progress-striped active">
         <div class="bar" style="width: 0%;"></div>
      </div>
    </div>

    <!-- your model code -->
    <ul class="nav nav-tabs nav-stacked">
      <li ng-repeat="line in lines">
        {{line.Id}}
      </li>
    </ul>

回答by Matej

You will want to use the $rootScopebecause monitoring a controller's $scopeis limited to the controller, and as it happens you're switching from one view (one controller) to another view (another controller). So it would make sense to have one-code-fit-all.

您将需要使用 ,$rootScope因为监控控制器$scope仅限于控制器,并且碰巧您正在从一个视图(一个控制器)切换到另一个视图(另一个控制器)。因此,拥有一种通用代码是有意义的。

$rootScope.$on('$stateChangeStart', 
function(event, toState, toParams, fromState, fromParams){ ... })

In that function set the $rootScope.isLoadingStatewhich will display your loading indicator.

在该函数中设置$rootScope.isLoadingState将显示您的加载指示器。

Then use

然后使用

$rootScope.$on('$stateChangeSuccess', 
function(event, toState, toParams, fromState, fromParams){ ... })

To unset that variable.

取消设置该变量。

Complete reference here

完整参考在这里

回答by Jeremy Reed

You can create a directive that will show based on a broadcast that you send before and after a service call, which you could put on $rootScope. So if you're calling a factory to handle dishing out generic POST/GET calls then right before the call you can call a function on $rootScope, such as "$rootScope.startLoading()" and when it finishes call "$rootScope.doneLoading()", where each of these methods broadcast an event for you to pick up on your directive. Then you just handle on your directive to catch the events, "scope.$on("startLoading", func(..." and have it insert/show a loading div template into the DOM and run, then also have a catch for done loading to remove/hide it.

您可以创建一个指令,该指令将根据您在服务调用之前和之后发送的广播进行显示,您可以将其放在 $rootScope 上。因此,如果您正在调用工厂来处理通用的 POST/GET 调用,那么就在调用之前,您可以在 $rootScope 上调用一个函数,例如“$rootScope.startLoading()”,当它完成时调用“$rootScope.startLoading()”。 doneLoading()”,其中每个方法都会广播一个事件供您接收指令。然后你只需处理你的指令来捕获事件,“scope.$on("startLoading", func(..." 并让它插入/显示一个加载 div 模板到 DOM 中并运行,然后还有一个捕获完成加载以删除/隐藏它。

That way you can have a nice general loading overlay.

这样你就可以有一个很好的通用加载覆盖。