Angularjs:如何在$ routeProvider中使用'resolve'时显示加载图标?
以下代码通过服务读取,并在网页上显示特定“页面类别”(string)的“页面”对象列表。 使用$ routeProvider.when()中的resolve对象属性,我可以推迟更新视图,直到新值准备就绪。
两个问题:
-
当要求一个新的页面列表,我想显示一个加载图标。 当从服务器开始读取(并且应该显示加载图标)时,如何检测(以非黑客的方式)事件? 我想我可以在服务中做一些像$('。pages-loading-icon')。show(),但是发现太过于依赖于服务的GUI。
-
当新的价值准备好了,我希望旧的淡出,新的淡入。什么是“angular”的方式来做到这一点? 我试图在控制器中使用$ watch来做到这一点,但是这会导致在淡出开始前不久显示新的值。
代码:
app.js:
$routeProvider.when('/:cat', { templateUrl: 'partials/view.html', controller: RouteCtrl, resolve: RouteCtrl.resolve});
controllers.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:读取的最后一页存储在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
<ul > <li ng-repeat="page in pages"> <a href="#{{params.cat}}/{{page.slug}}">{{page.title}}</a> </li> </ul>
不完全确定这是否会在您的代码中工作,因为您有$资源集成。 但是可能需要查看angular度事件: $routeChangeStart
和$routeChangeSuccess
。
在html中:
<span ng-show="isViewLoading"> loading the view... </span>
在控制器(它定义了上面的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; });
angular度的路由系统似乎有点有限..
这为我解决了这个问题:
http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm
此外,关于事件触发两次:如果你设置一个路线做映射到“a / b / c”angular度自动设置另一条路线,“a / b / c /”(带有斜线)redirect到第一个(和反之亦然),并且都触发事件。 我只是testing路由参数的存在。
关于路由系统的有限条件:有angular度的这个拉 ,以扩展它的能力。
你也可以使用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>
您将需要使用$rootScope
因为监视控制器的$scope
只限于控制器,正好从一个视图(一个控制器)切换到另一个视图(另一个控制器)。 所以,一个代码适合所有人都是有道理的。
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ ... })
在该函数中设置$rootScope.isLoadingState
,它将显示您的加载指示器。
然后使用
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ ... })
取消设置该variables。
完整的参考
我喜欢'ng-show'
…但是,Angular UI项目的'ui-if'
更好一些。因为从DOM中删除HTML代码…
<span ui-if = "isViewLoading"> loading the view... </span>
_e
您可以创build一个指令,根据您在服务调用之前和之后发送的广播来显示,您可以将它放在$ rootScope上。 所以,如果你打电话给一个工厂去处理通用的POST / GET调用,那么在调用之前,你可以调用$ rootScope的函数,比如“$ rootScope.startLoading()”,当它完成时调用“$ rootScope”。 doneLoading()“,在这些方法中,每个方法都会广播一个事件,让你select你的指令。 然后你只要处理你的指令来捕捉事件,“范围。$ on(”startLoading“,func(…”),并插入/显示一个加载div模板到DOM并运行,然后还有一个catch完成加载删除/隐藏它。
这样你可以有一个很好的通用加载覆盖。