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
Angularjs: How to display loading-icon when using 'resolve' in $routeProvider?
提问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:
两个问题:
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.
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.
当要求一个新的页面列表时,我想显示一个加载图标。当从服务器开始读取(并且应该显示加载图标)时,如何检测(以非黑客的方式)事件?我想我可以在服务中做类似 $('.pages-loading-icon').show() 的事情,但发现它太依赖于 gui 太放在服务中了。
当新值准备好时,我希望旧值淡出,新值淡入。这样做的“角度”方式是什么?我曾尝试使用 $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.
这样你就可以有一个很好的通用加载覆盖。

