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

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);
});
}

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 app.run possibility of keeping data in app

There is a possibility in app.run I record any information in this case last at $stateParams and write to the $rootScoope?
It would be simple because I pull the server a coming collection mongodb and I just editing it throughout the app.
I want to prevent in all state entries I have to pull the less data.
my app.run in test:
.run(function($rootScope, $state, $stateParams, CLIENTS) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
console.log($stateParams);
CLIENTS.getList({client: client})
.then(function(res){
console.log(res);
});
});
Follow this path:
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
// get Client data
if(!$rootScope.clientSet) {
CLIENTS.getList({client: toParams.client})
.then(function(res){
$rootScope.clientSet = res[0];
});
}
}
https://github.com/angular-ui/ui-router/wiki#state-change-events
You can listen for events so you can refresh data in rootScope.
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, 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.

ui-router change, when to remove the old html

I've tested this in chrome, and added a break in the $scope.init in Ctrl2
but then when I go to route2 from route1, the chrome debugger stays at $scope.init of Ctrl2, but I see that ctrl1.html is still there.
.state("main.route1", {
url: "/route1",
controller: 'Ctrl1',
templateUrl: 'views/ctrl1.html'
})
.state("main.route2", {
url: "/route2",
controller: 'Ctrl2',
templateUrl: 'views/ctrl2.html'
})
So, how does the ui-router work? Isn't it supposed to go to ctrl2.html, and then execute Ctrl2? Why did it enter Ctrl2 but the ctrl1.html is still displayed?
I'm not sure if it is the same in ng-view, I haven't tested that.
Check js console to make sure you don't have errors in your angular controller
Add following run block to your module to catch state change error
.run(function ($rootScope, $state) {
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
console.log(fromState.name + ' to ' + toState.name);
});
$rootScope.$on('$stateChangeError',
function (event, toState, toParams, fromState, fromParams, error) {
alert(error);
event.preventDefault();
});
});

Resources