簡體   English   中英

(Angular-ui-router)在解析過程中顯示加載動畫

[英](Angular-ui-router) Show loading animation during resolve process

這是一個兩部分問題:

  1. 我在$ stateProvider.state()中使用resolve屬性來在加載控制器之前獲取某些服務器數據。 如何在此過程中顯示加載動畫?

  2. 我有子狀態也使用resolve屬性。 問題是ui-router似乎想要在加載任何控制器之前完成所有解析。 有沒有什么辦法可以讓他們在解析后解析父控制器,而不必等待所有的子解析? 對此的答案也可能解決第一個問題。

編輯:這是一個更簡單的解決方案,測試和工作很好:

在我的主控制器中,我只是

$scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
    if (toState.resolve) {
        $scope.showSpinner();
    }
});
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
    if (toState.resolve) {
        $scope.hideSpinner();
    }
});

當狀態更改完成時,無論何時我們要進入有任何需要解決的狀態並隱藏它,都會顯示微調器。 您可能想要添加一些檢查狀態層次結構(即如果正在加載的父狀態解析某些內容,也會顯示微調器),但此解決方案對我來說很好。

這是我的舊建議供參考,作為替代方案:

  1. 在應用程序控制器中,監聽stateChangeStart事件並檢查是否要在解析期間切換到要顯示微調器的狀態(請參閱https://github.com/angular-ui/ui-router/wiki/快速參考#wiki-events-1

     $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ if (toState.name == 'state.with.resolve') { $scope.showSpinner(); //this is a function you created to show the loading animation } }) 
  2. 當你最終調用控制器時,你可以隱藏微調器

     .controller('StateWithResolveCtrl', function($scope) { $scope.hideSpinner(); }) 

您還可能希望通過偵聽$stateChangeError事件並在處理錯誤時隱藏動畫來檢查解析期間可能發生的任何錯誤。

當你在控制器之間分配微調器的邏輯時,這並不完全干凈,但這是一種方式。 希望能幫助到你。

我開發了以下解決方案,它對我來說非常有效。

1.添加以下app.run

app.run(function($rootScope){

    $rootScope
        .$on('$stateChangeStart', 
            function(event, toState, toParams, fromState, fromParams){ 
                $("#ui-view").html("");
                $(".page-loading").removeClass("hidden");
        });

    $rootScope
        .$on('$stateChangeSuccess',
            function(event, toState, toParams, fromState, fromParams){ 
                $(".page-loading").addClass("hidden");
        });

});

2.將加載指示器放在ui視圖的正上方。 將id =“ui-view”添加到ui-view div。

<div class="page-loading">Loading...</div>
<div ui-view id="ui-view"></div>

3.將以下內容添加到您的CSS中

.hidden {
  display: none !important;
  visibility: hidden !important;
}

注意:

A.以上代碼將在兩種情況下顯示加載指示器1)當角度應用程序第一次加載時2)當視圖更改時。

B.如果您不希望在角度應用第一次加載時(在加載任何視圖之前)顯示指標,則將隱藏的類添加到加載div中,如下所示

<div class="page-loading hidden">Loading...</div>

我發現由於網絡訪問,使用角度加載條非常適合長時間的解析。

如果屬性已解決,如何將內容添加到將由ui-router填充的div中?

在你的index.html

<div ui-view class="container">
    Loading....
</div>

現在,用戶將在解析屬性時看到“正在加載...”。 一切准備就緒后,內容將由ui-router替換為您的應用內容。

我使用的動畫gif僅在$http有未決請求時顯示。

在我的基頁模板中,我有一個導航欄和導航欄控制器。 控制器的相關部分如下所示:

controllers.controller('NavbarCtrl', ['$scope', '$http',
    function ($scope, $http) {
        $scope.hasPendingRequests = function () {
            return $http.pendingRequests.length > 0;
        };
    }]);

我的html中的相應代碼是:

<span class="navbar-spinner" ng-show="hasPendingRequests()">
    <img src="/static/img/spinner.gif">
</span>

我希望有所幫助!

我的想法是在$stateChangeStart上的轉換狀態之間走狀態圖,並收集所有涉及的視圖。 然后,每個ui-view指令都會ui-view轉換中是否包含相應的視圖,並在其元素上添加'ui-resolving'類。

plunker演示引入了兩個根狀態: firstsecond ,后者有兩個子狀態second.sub1second.sub2 second.sub2也針對屬於其祖父母的footer視圖。

當在任何狀態(任何頁面)之間進行頁面導航時,這是全局加載器,放在app.js中

.run(
    ['$rootScope',
        function($rootScope) {
            $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
                $rootScope.preloader = true;
            })
            $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
                $rootScope.preloader = false;
            })
        }
    ])

在html中:

<div ng-show="preloader">Loading...</div>

我更喜歡使用指令來匹配任何加載活動,主要是為了保持我的代碼庫清潔

angular.module('$utilityElements', [])
.directive('loader',['$timeout','$rootScope', function($timeout, $rootScope) {
    return {
      restrict: 'A',
      template: '<div id="oneloader" class="hiddenload">loading...</div>',
      replace: true,
      compile: function (scope, element, attrs) {
        $timeout(function(){
          $rootScope
              .$on('$stateChangeStart',
                  function(event, toState, toParams, fromState, fromParams){
                      $("#oneloader").removeClass("hiddenload");
              });

          $rootScope
              .$on('$stateChangeSuccess',
                  function(event, toState, toParams, fromState, fromParams){
                      //add a little delay
                      $timeout(function(){
                        $("#oneloader").addClass("hiddenload");
                      },500)
              });
        }, 0);
      }
    }
  }]);

之后不再使用$stateChangeStart等替換為Transition Hooks 因此,對於Stefan Henze的答案,更新版本將是:

$transitions.onStart({}, function(transition) {
  if (transition.to().resolve) {
    $scope.showSpinner();
  }
});

$transitions.onSuccess({}, function(transition) {
  if (transition.to().resolve) {
    $scope.hideSpinner();
  }
});

您可以在父控制器中使用它。 記得注入$transitions -

.controller('parentController',['$transitions',function($transitions){...}]);

另外,請記住,作為空對象的resolve仍將呈現transition.to().resolve == true ,因此不要在狀態聲明中留下空占位符resolve

我的想法在路由器中使用resole時使用視圖它工作真棒。 試試這個。

//edit index.html file 
<ion-nav-view>
    <div ng-show="loadder" class="loddingSvg">
        <div class="svgImage"></div>
    </div>
</ion-nav-view>

// css file

.loddingSvg {
    height: 100%;
    background-color: rgba(0, 0, 0, 0.1);
    position: absolute;
    z-index: 99;
    left: 0;
    right: 0;
}

.svgImage {
    background: url(../img/default.svg) no-repeat;
    position: relative;
    z-index: 99;
    height: 65px;
    width: 65px;
    background-size: 56px;
    top: 50%;
    margin: 0 auto;
}

// edit app.js

 .run(function($ionicPush, $rootScope, $ionicPlatform) {




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

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

});

如果有人正在使用ngRoute ,在加載下一個視圖之前等待resolve ,並使用angular-bootstrap-ui作為ui,則可以執行以下操作

app.config([
  "$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
    return $routeProvider.when("/seasons/:seasonId", {
      templateUrl: "season-manage.html",
      controller: "SeasonManageController",
      resolve: {
        season: [
          "$route", "$q", "$http", "$modal", function($route, $q, $http, $modal) {
            var modal, promise, seasonId;
            modal = $modal.open({
              backdrop: "static",
              template: "<div>\n  <div class=\"modal-header\">\n    <h3 class=\"modal-title\">\n      Loading...\n    </h3>\n  </div>\n  <div class=\"modal-body\">\n    <progressbar\n      class=\"progress-striped active\"\n      value=\"'100'\">\n    </progressbar>\n  </div>\n</div>",
              keyboard: false,
              size: "lg"
            });
            promise = $q.defer();
            seasonId = $route.current.params.seasonId;
            $http.get("/api/match/seasons/" + seasonId).success(function(data) {
              modal.close();
              promise.resolve(data);
            }).error(function(data) {
              modal.close();
              promise.reject(data);
            });

            return promise.promise;
          }
        ]
      }
    });
  }
]);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM