Angular, ui-router: show loading when change state - angularjs

Is there a way in angular that when I want switch to another state (ui-sref) that i can show some load icon until the second state is loaded?

yes angular ui.router has events which you can listen:
$stateChangeStart - fired when the transition begins.
$stateChangeSuccess - fired once the state transition is complete.
following this you can write preloader functionality
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
$rootScope.preloader = false;
}
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
$rootScope.preloader = true;
}
and write some <div> in your body element and show/hide it with this variable
eg.
<body>
<div ng-show="preloader"></div>
</body>

Related

How can i get values from $stateChanges

Please Helpme How can i get values from $statechangeStart and $stateChaneSuccess
MyApp.js
app.run(function ($rootScope) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams, options) {
$scope.IsLoading = true;
})
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams, options) {
$scope.IsLoading = False;
})
})
Home.js
///Here How can i use IsLoading
Use providers (generally a service or factory, maybe a .value) to define things that can be injected into controllers.
https://docs.angularjs.org/guide/providers
https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md
Best practice for using $rootscope in an Angularjs application?
angular.module('myapp',[])
.value('SharedObject', {isLoading:true})
.run(function($timeout, SharedObject){
$timeout(function(){SharedObject.isLoading = false}, 2000);
})
.controller('MyCtrl', function(SharedObject){
this.SharedObject = SharedObject;
})
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
</head>
<body ng-controller="MyCtrl as myctrl">
{{myctrl.SharedObject}}
</body>
</html>
Because you are adding this logic in the run function, you'll want to set the isLoading property on the $rootScope object, not the $scope object, which does not exist in this context:
app.run(function ($rootScope) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams, options) {
$rootScope.isLoading = true;
});
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams, options) {
$rootScope.isLoading = false;
});
});
Then, in your template that has access to $rootScope, you can show a loading screen by using ngIf, which conditionally adds elements to the DOM:
<div ng-if="isLoading" class="loading-screen">
Loading...
</div>

Angular JS, unable to get handle to rootScope [duplicate]

This question already has answers here:
Cannot get to $rootScope
(3 answers)
Closed 5 years ago.
I am using angular 1.5.x
Below is my routing logic but I am not able to get a handle of the rootScope.
Please can you advise what could be wrong?
UPDATE: I have updated the routing logic as per the answer post below.
I am still not able to hit the controller.
(function() {
'use strict';
angular
.module('icebergApp')
.config(setupRouting);
setupRouting.$inject = ['$stateProvider', '$urlRouterProvider', '$rootScope'];
function setupRouting($stateProvider, $urlRouterProvider, $rootScope) {
$urlRouterProvider.otherwise("/iceberg-ui");
$stateProvider
.state('iceberg.reconlist', {
url: "/iceberg-ui",
templateUrl: "app/iceberg/reconlist/reconlist.view.html",
controller: 'ReconListController as vm'
})
$rootScope.$on('$stateChangeStart',function(event, toState, toParams, fromState, fromParams){
console.log('$stateChangeStart to '+toState.name+'- fired when the transition begins. toState,toParams : \n',toState, toParams);
});
$rootScope.$on('$stateChangeError',function(event, toState, toParams, fromState, fromParams, error){
console.log('$stateChangeError - fired when an error occurs during transition.');
console.log(arguments);
});
$rootScope.$on('$stateChangeSuccess',function(event, toState, toParams, fromState, fromParams){
console.log('$stateChangeSuccess to '+toState.name+'- fired once the state transition is complete.');
});
$rootScope.$on('$viewContentLoading',function(event, viewConfig){
console.log('$viewContentLoading - view begins loading - dom not rendered',viewConfig);
});
$rootScope.$on('$stateNotFound',function(event, unfoundState, fromState, fromParams){
console.log('$stateNotFound '+unfoundState.to+' - fired when a state cannot be found by its name.');
console.log(unfoundState, fromState, fromParams);
});
}
}());
CONTROLLER
(function() {
'use strict';
var myApp = angular.module('iceberg.reconlist', ['ui.router']);
myApp.controller('ReconListController', ReconListController);
ReconListController.$inject = ['ReconListService'];
function ReconListController(ReconListService) {
var vm = this;
}
}());
MODULE
(function() {
'use strict';
angular.module('icebergApp', [
'ui.router',
'iceberg.reconlist'
]);
angular.module('iceberg.reconlist', [
]);
}());
$rootScope is not available in .config(). Only providers are available there. The thing you must do is splitting your code to put the $rootScope part into a .run method.
angular
.module('app')
.config(setupRouting);
setupRouting.$inject = ['$stateProvider', '$urlRouterProvider'];
function setupRouting($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/iceberg-ui");
$stateProvider
.state('iceberg.reconlist', {
url: "/iceberg-ui",
templateUrl: "app/iceberg/reconlist/reconlist.view.html",
controller: 'ReconListController as vm'
})
}
}());
angular.module('app').run(setupRoutingEventListeners);
setupRouting.$inject = ['$rootScope'];
function setupRoutingEventListeners($rootScope) {
$rootScope.$on('$stateChangeStart',function(event, toState, toParams, fromState, fromParams){
console.log('$stateChangeStart to '+toState.name+'- fired when the transition begins. toState,toParams : \n',toState, toParams);
});
$rootScope.$on('$stateChangeError',function(event, toState, toParams, fromState, fromParams, error){
console.log('$stateChangeError - fired when an error occurs during transition.');
console.log(arguments);
});
$rootScope.$on('$stateChangeSuccess',function(event, toState, toParams, fromState, fromParams){
console.log('$stateChangeSuccess to '+toState.name+'- fired once the state transition is complete.');
});
$rootScope.$on('$viewContentLoading',function(event, viewConfig){
console.log('$viewContentLoading - view begins loading - dom not rendered',viewConfig);
});
$rootScope.$on('$stateNotFound',function(event, unfoundState, fromState, fromParams){
console.log('$stateNotFound '+unfoundState.to+' - fired when a state cannot be found by its name.');
console.log(unfoundState, fromState, fromParams);
});
}

Debugging angular ui-router under ionic

I am pretty new to Angularjs and Ionic and I am trying to warp my head around the status based routing. The biggest hurdle is that it seems to difficult to drill in without a decent way to debug what's happening.
There is some help for debugging angularjs ui-routing in this question and answer - But the example is for just AngularJS and not for Ionic and I am struggling to figure out how to implement this solution in Ionic.
In AngularJS the debug code would go here:
angular.module('MyModule').run(['$rootScope',function($rootScope){ // put the event handlers here }]);
But in Ionic the according code looks like this:
run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
Can anyone help me understand how to inject the debug code here?
Thanks to the comment from George Stocker I figured it out. The resulting code looks like this:
angular.module('starter', [])
.run(['$rootScope',function($rootScope){
$rootScope.$on('$stateChangeStart',function(event, toState, toParams, fromState, fromParams){
console.log('$stateChangeStart to '+toState.to+'- fired when the transition begins. toState,toParams : \n',toState, toParams);
});
$rootScope.$on('$stateChangeError',function(event, toState, toParams, fromState, fromParams, error){
console.log('$stateChangeError - fired when an error occurs during transition.');
console.log(arguments);
});
$rootScope.$on('$stateChangeSuccess',function(event, toState, toParams, fromState, fromParams){
console.log('$stateChangeSuccess to '+toState.name+'- fired once the state transition is complete.');
});
$rootScope.$on('$viewContentLoaded',function(event){
console.log('$viewContentLoaded - fired after dom rendered',event);
});
$rootScope.$on('$stateNotFound',function(event, unfoundState, fromState, fromParams){
console.log('$stateNotFound '+unfoundState.to+' - fired when a state cannot be found by its name.');
console.log(unfoundState, fromState, fromParams);
});
}])
Here you can inject the AngularJS logging service to your Ionic project, in just one run method call:
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
.run(['$rootScope', '$log', '$ionicPlatform', function ($rootScope, $log, $ionicPlatform) {
$ionicPlatform.ready(function () {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
// Debug stuff...
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
$log.debug('$stateChangeStart to ' + toState.name + '- fired when the transition begins. toState,toParams : \n', toState, toParams);
});
$rootScope.$on('$stateChangeError', function (event, toState, toParams, fromState, fromParams, error) {
$log.debug('$stateChangeError - fired when an error occurs during transition.');
$log.debug(arguments);
});
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
$log.debug('$stateChangeSuccess to ' + toState.name + '- fired once the state transition is complete.');
});
// $rootScope.$on('$viewContentLoading',function(event, viewConfig){
// // runs on individual scopes, so putting it in "run" doesn't work.
// $log.debug('$viewContentLoading - view begins loading - dom not rendered',viewConfig);
// });
$rootScope.$on('$viewContentLoaded', function (event) {
$log.debug('$viewContentLoaded - fired after dom rendered', event);
});
$rootScope.$on('$stateNotFound', function (event, unfoundState, fromState, fromParams) {
$log.debug('$stateNotFound ' + unfoundState.name + ' - fired when a state cannot be found by its name.');
$log.debug(unfoundState, fromState, fromParams);
});
}])
For production you can disable debug, with this in your config block:
.config(function($logProvider){
$logProvider.debugEnabled(false);
});

How to detect state start completion with a combination of $stateChangeStart, $stateChangeSuccess, $state with ui-router for angularjs

I want to impliment a loader image for each state change, and that will be apply to the whole page whenever the state changes. I tried to at least see if they exist, but somehow, I receive not definfed for $stateChangeStart for both when state change start and completed. I wonder what is the best way to do it? Because I want to put that $stateChangeStart as a var for ng-hide directive, so that when every time a state change starts, the loader will show, and (I assume) when $stateChangeSuccess is becoming defined, then its change of state is completed?
Please advice if anything of what I intent to do is wrong and better way to do it. Because I want to build the loader to be directive by itself and its reusable.
Below is the code I try to test these 3 objects.
app.run([
'$rootScope','$location','$state','$stateParams',/*'$templateCache',*/
function (
$rootScope, $location, $state, $stateParams/*, $templateCache*/ ) {
console.log("app run")
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
console.log("state start-------------------------")
console.log($stateChangeStart,"$stateChangeStart ")
console.log($stateChangeSuccess,"$stateChangeSuccess ")
console.log($state);
});
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
console.log("state $stateChangeSuccess-------------------------")
console.log($stateChangeStart,"$stateChangeStart ")
console.log($stateChangeSuccess,"$stateChangeSuccess ")
console.log($state);
});
}]);
Try something like this:
app.run([
'$rootScope','$location','$state','$stateParams',/*'$templateCache',*/
function (
$rootScope, $location, $state, $stateParams/*, $templateCache*/ ) {
console.log("app run")
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
$rootScope.showLoading = true;
});
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
$rootScope.showLoading = false;
});
}]);
and then bind the ng-show to the showLoading property.

How to $watch state change of $stateProvider in AngularJS?

I know that I can run:
scope.$watch(someItem, function(){})
But I can't figure out a way to watch over change of $state.$current.name in my application.
It's in the docs: https://github.com/angular-ui/ui-router/wiki#state-change-events
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
// do something
})
This works:
$scope.$watch(function(){
return $state.$current.name
}, function(newVal, oldVal){
//do something with values
})

Resources