how to inject $http service on state change event in angular js? - angularjs

I am using Ui-Route in angular js, and I want to call $http service on every state change. When I inject $http service in statechange event it gives an error of circular dependency or even I inject in interceptor the same error is showing. Please help me with this.
Thank you

You can put the service call in resolve for state
$stateProvider
.state('business-page', {
url: '/your-listing/:id',
controller: 'BusinessCtrl as vm',
templateUrl: 'pages/business/business.html',
title: 'Details',
resolve: {
listing: ['appDataFactory', '$stateParams', function (appDataFactory, $stateParams) {
return appDataFactory.getListingData($stateParams.id);
}]
}
})
where appDataFactory will be the service for $http request and the response can be solved as injection on the state controller

Related

AngularJS UI-Router Access $stateParams from State's data object

Given the following state in ui-router:
.state('some.state', {
url: '/some/:viewType',
templateUrl: 'myTemplate.html',
controller: 'SomeStateController',
controllerAs: 'vm',
data: {
authorizedFor: [SOME_ROLE]
}
}
I'm trying to use the "data" object for a state to help control access to authorized states. Separately, I handle the $stateChangeStart event to look at data.authorizedFor and act accordingly.
The problem, though, is that the list of authorized roles might change based on the value of :viewType. I thought I could let data:{} be a function, inject $stateParams, and handle the logic there...but that won't do.
So, I tried using the params object instead, but at the $stateChangeStart time, the :viewType is not yet accessible from $state.params or $stateParams.
Stepping through in dev tools, I noticed that $state.transitionTo.arguments is populated, but it seems awfully hacky to go that route.
params: {
authorizedFor: function($state) {
console.log($state.transitionTo.arguments[1].viewType); // has value I need
}
}
Any suggestions?
My suggestion is to use resolve to provide your controller with content or data that is custom to the state. resolve is an optional map of dependencies which should be injected into the controller.
If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $stateChangeSuccess event is fired.
for example:
$stateProvider
.state('profile', {
url: '/profile',
templateUrl: 'profile.html',
resolve:{
'ProfileService': function(ProfileService){
return ProfileService.promise_skillRecommendation_mock;
}
}
})
The profileService code:
var app = angular.module('app').service("ProfileService", function($http){
var myData = null;
var promise_skillRecommendation_mock =
$http.get('Mock/skillRecommendation-mock.json')
.success(function(data){
myData = data;
});
return{
promise_skillRecommendation_mock: promise_skillRecommendation_mock,
get_skillRecommendation: function(){
return myData;
}
};
});
and the controller code which will use this service is:
angular.module('app').controller('ProfileController', function($scope, $http, ProfileService){
$scope.skillRecommendation = ProfileService.get_skillRecommendation();
The object in resolve below must be resolved (via deferred.resolve() if they are a promise) before the controller is instantiated. Notice how each resolve object is injected as a parameter into the controller.
by using this code, the page will be displayed only after that the promise will be resolved.
for more info please view this page: https://github.com/angular-ui/ui-router/wiki

$state, $stateParams, getting undefined object

I am getting unexpected results from both methods.
I have my $state configed
$stateProvider
.state('status', {
url: "/status/:payment",
controller: 'QuestCtrl',
templateUrl: "index.html"
});
And on the Controller I have:
angular.module('quest').controller('QuestCtrl',function($scope,$stateParams,$state){
console.log($stateParams.payment); // undefined
console.log($state); // Object {params: Object, current: Object, $current: extend, transition: null}
}
I already used $stateParams in other projects and it worked but now I can't figure out what is going on here..
['$scope','$stateParams','$state',
function($scope, $http, $stateParams, $state)
The names of the services don't match with the variables.
So $http is actually the $stateParams service, $stateParams is actually the $state service, and $state is undefined.
My advice: stop using this array notation, which clutters the code and is a frequent source of bugs. Instead, use ng-annotate as part of the build procedure, which will do it, correctly, for you.
As I already commented above You forgot to inject $http service
angular.module('quest').controller('QuestCtrl',
['$scope','$http','$stateParams','$state',function($scope,$http,$stateParams,$state){
console.log($stateParams); // Empty Object
console.log($stateParams.payment); // Empty Object
console.log($state); // I get the entire state, I can see that my params are there.
console.log($state.params);
}
So your parameters mismatch and it turns out you will get $state in $stateparms and $state is empty.
And $http hold $state :P
Hope it helps :)
With the ng-annotate library, the controller can be also initiated like this:
angular.module('quest')
.controller('QuestCtrl', function ($scope,$http,$stateParams,$state) {
});
In this case you are avoiding problems with the injected objects ordering. Look at: https://github.com/olov/ng-annotate
If you are building your application with Grunt, use: grunt-ng-annotate package.
Missing parameter in routes.js
My example:
.state('menu.cadastroDisplay', {
url: '/page9',
views: {
'side-menu21': {
templateUrl: 'templates/cadastroDisplay.html',
controller: 'cadastroDisplayCtrl'
}
},
params: { 'display': {} }
})
Without this params in routes the $stateParams.yourParam always returns undefined.
Call 'ngInject'
constructor($scope, $reactive, $stateParams, $state, $sce) {
'ngInject'

Angular initializing data in $routeProvider using resolve

I have a AngularJS application and have a requirement to initialize data from a REST API before the controller initializes. I use the "resolve" in the routeProvider and also injected the relevant value in the controller in order to make this data available. The code snippets are as follows:
RouteProvider code snippet:
myApp.config(function($routeProvider) {
$routeProvider
....
.when('/account', {
templateUrl : path + 'admin/js/pages/inputs/account.html',
controller : 'mainController',
resolve: {
data: function() {
return $http.get(api_path + 'dashboard/get_accounts');
}
}
})
myApp.controller('mainController', function($scope,$http, data, $routeParams, DataService) {
...
console.log(data);
}
The console is supposed display the data by I get the following error " Error: [$injector:unpr] Unknown provider: dataProvider <- data "
Your help much appreciated.
It's because the data provider has not instantiated yet and it is instantiating the controller before the provider is ready, coming through as an undefined and unknown provider.
Try something like this that returns a promise:
myApp.config(function($routeProvider, $q) {
$routeProvider, $q
....
.when('/account', {
templateUrl : path + 'admin/js/pages/inputs/account.html',
controller : 'mainController',
resolve: {
data: function() {
return $q.all($http.get(api_path + 'dashboard/get_accounts'));
}
}
})
Now, the controller won't instantiate until the promise has resolved completely. As per the documentation for $routeProvider and how it handles promises in the resolve.
$routeProvider on Angular's website
resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired.

Angular Route Precheck

I have angular app
<body ng-app="appName">
<div class="container" ng-view=""></div>
I have routes
$routeProvider
.when('/', {
templateUrl: 'partials/main',
controller: 'MainCtrl'
})
.when('/login', {
templateUrl: 'partials/login',
controller: 'LoginCtrl'
})
I want to call a service before every route. Say for example if I have not loaded the profile data I want load profile data and store it in $rootscope. How should I do this?
You can use the $route's resolve property to call a function that will be executed prior to the route change:
From the AngularJS API Docs:
resolve - {Object.<string, function>=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired. The map object is:
This is usually meant to inject the route's controller with additional parameters but there's no reason you could do more.
$routeProvider
.when('/login',{
templateUrl : 'partials/login',
controller: 'loginCtrl',
resolve : {
some_extra_controller_param : ['$route','someService',function($route,someService){
// do stuff here that you would feel necessary to have done prior to route change
someService.doSomething();
return true; // or return an object of data maybe your controller could use
]}
}
});
Of course the some_extra_controller_param will be injected into your controller as the last parameter so make sure you return something in the resolve, loginCtrl might look like this:
.controller('loginCtrl',['$scope','some_extra_controller_param',function($scope,some_extra_controller_param){
...
]});
EDIT: You may want to setup the resolve function to use promises as the route's controller will wait on promises to be "resolved" before instantiating the controller.
EDIT:
var myBeforeRouteCheck = {
something_to_be_resolved : ['$route','someService',function($route,someService){
// assuming your service runs some kind of function that returns a promise
return someService.someFunc().then(
function(data){
...do successful things...;
return somethingToInjectedParam;
},
function(){
... error ...
return false;
});
}]
};
then in your route:
.when('/login',{
...
resolve: myBeforeRouteCheck
}

injecting service into angularjs app config

I am trying to inject $http serivce into app config, but getting "unknown provider $http error".
woi.config(['$routeProvider', '$locationProvider','$http', function($routeProvider, $locationProvider,$http){
$routeProvider
.when("/channels", {
templateUrl: test,
resolve: {
app: function($http){
}
}
})
]});
My question is , is it possible to inject $http serivce in app config ,and if not then what are the other ways to do ajax call before controller and template is called.
Thanks,
You can directly pass $http or any dependency into the function, without defining it at config function. The DI framework of Angular would inject dependencies for resolve object functions.

Resources