javascript - template - ui view angular js
(Angular-ui-enrutador) Muestra la animaciĆ³n de carga durante el proceso de resoluciĆ³n (11)
Esta es una pregunta de dos partes:
Estoy usando la propiedad resolve dentro de $ stateProvider.state () para capturar ciertos datos del servidor antes de cargar el controlador. ¿Cómo podría obtener una animación de carga para mostrar durante este proceso?
Tengo estados secundarios que también utilizan la propiedad de resolución. El problema es que ui-router parece querer finalizar todas las resoluciones antes de cargar cualquier controlador. ¿Hay alguna manera de que pueda cargar los controladores principales una vez que se hayan resuelto sus resoluciones, sin tener que esperar a que se resuelva todo el contenido? Una respuesta a esto probablemente también resolverá el primer problema.
¿Qué le parece agregar contenido al div que se completará con ui-router una vez que las propiedades se hayan resuelto?
En su index.html
<div ui-view class="container">
Loading....
</div>
El usuario verá ahora "Cargando ..." mientras se resuelven las propiedades. Una vez que todo esté listo, el contenido será reemplazado por el enrutador uui con el contenido de tu aplicación.
Desarrollé la siguiente solución que funciona perfectamente para mí.
1. Agregue la siguiente aplicación.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. Coloque el indicador de carga justo arriba de la vista de ui. Agregue id = "ui-view" a ui-view div.
<div class="page-loading">Loading...</div>
<div ui-view id="ui-view"></div>
3. agregue lo siguiente a su css
.hidden {
display: none !important;
visibility: hidden !important;
}
NOTA:
A. El código anterior mostrará el indicador de carga en dos casos 1) cuando la aplicación angular se carga la primera vez 2) cuando se cambia la vista.
B. Si no desea que se muestre el indicador cuando la aplicación angular se carga por primera vez (antes de cargar cualquier vista), agregue la clase oculta al div de carga como se muestra a continuación
<div class="page-loading hidden">Loading...</div>
EDITAR: Aquí hay una solución aún más fácil, probada y funcionando muy bien:
En mi controlador principal, simplemente tengo
$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();
}
});
Esto muestra el spinner cada vez que estamos a punto de ir a un estado que tiene algo que resolver y lo oculta, cuando se completa el cambio de estado. Es posible que desee agregar un poco de control de la jerarquía de estado (es decir, también mostrar el spinner si un estado principal que se está cargando resuelve algo) pero esta solución funciona bien para mí.
Aquí está mi vieja sugerencia de referencia y como alternativa:
En el controlador de su aplicación, escuche el evento
stateChangeStart
y verifique si está a punto de cambiar al estado en el que desea mostrar un spinner durante la resolución (consulte https://github.com/angular-ui/ui-router/wiki/Quick-Reference#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 } })
Cuando finalmente se llama al controlador, puedes ocultar el girador
.controller(''StateWithResolveCtrl'', function($scope) { $scope.hideSpinner(); })
También es posible que desee comprobar si se produjeron errores durante la resolución al escuchar el evento $stateChangeError
y ocultar la animación mientras maneja el error.
Esto no está del todo limpio ya que distribuye la lógica para la ruleta entre los controladores, pero es una manera. Espero eso ayude.
El uso de $stateChangeStart
y similares se han depreciado y reemplazado con Transition Hooks . Entonces, para la respuesta de Stefan Henze, la versión actualizada sería:
$transitions.onStart({}, function(transition) {
if (transition.to().resolve) {
$scope.showSpinner();
}
});
$transitions.onSuccess({}, function(transition) {
if (transition.to().resolve) {
$scope.hideSpinner();
}
});
Puede usar esto en su controlador principal. Recuerde inyectar $transitions
-
.controller(''parentController'',[''$transitions'',function($transitions){...}]);
Además, tenga en cuenta que una resolve
que sea un objeto vacío seguirá haciendo que transition.to().resolve == true
, por lo que no deje una resolve
marcador de posición vacía en la declaración de estado.
He descubierto que el uso de la angular-loading-bar funcionó muy bien durante mucho tiempo debido al acceso a la red.
Mi idea es recorrer el camino en el gráfico de estado entre estados en transición en $stateChangeStart
y recopilar todas las vistas involucradas. Luego, cada directiva ui-view
observa si la vista correspondiente está involucrada en la transición y agrega ''ui-resolving''
clase ''ui-resolving''
en su elemento.
La demostración de plunker introduce dos estados raíz: first
y second
, este último tiene dos subestados second.sub1
y second.sub2
. El estado second.sub2
también se dirige a la vista de footer
que pertenece a su abuelo.
Mi idea para usar view mientras usamos resol en el enrutador funciona de maravilla. prueba esto.
//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;
});
});
Prefiero usar una directiva para hacer coincidir cualquier actividad de carga, principalmente para mantener mi base de código limpia
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);
}
}
}]);
Si alguien está usando ngRoute
, espera resolve
antes de cargar la siguiente vista y usa angular-bootstrap-ui
para ui, puede hacer lo siguiente :
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;
}
]
}
});
}
]);
Utilizo un gif animado que se muestra solo cuando $http
tiene solicitudes pendientes.
En mi plantilla de página base, tengo una barra de navegación y un controlador de barra de navegación. La parte relevante del controlador se ve así:
controllers.controller(''NavbarCtrl'', [''$scope'', ''$http'',
function ($scope, $http) {
$scope.hasPendingRequests = function () {
return $http.pendingRequests.length > 0;
};
}]);
El código correspondiente en mi html es:
<span class="navbar-spinner" ng-show="hasPendingRequests()">
<img src="/static/img/spinner.gif">
</span>
¡Espero que eso ayude!
Este es un cargador para todo el mundo cuando la página navega entre cualquier estado (cualquier página), pone en 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;
})
}
])
En html:
<div ng-show="preloader">Loading...</div>