I have a file "controller.js" Which has homeController and sectionController defined.
in route.js
when('/home', {
templateUrl: 'view/main/home.html',
controller: 'homeController',
access: {
requiredLogin: false
}
}).
when('/section/:menu', {
templateUrl: 'view/main/section.html',
controller: 'sectionController',
access: {
requiredLogin: false
}
})
but when call to /section/ is made. I could still see $http request defined in homeController being made. Can anybody please tell me the reason and how to tackle this. A proper binding of controllers to the views.
Make sure the controller is not being instantiating in your html with ng-controller.
Apart from this, there was a use of $interval. In each cycle, a call was made. When a change in route occurred $interval was not destroyed and remain active. Found an explanation at angularjs $interval being called multiple times now the issue is resolved.
Related
Possible Duplicate of $http is getting called multiple times in AngularJS
Sorry I didn't have 50 reputations to comment on the same post.
We are calling the api's using http service and all the services have session id that been passed through cookiestore value. The api call doesn't work for first time as session id is null during first call and it works only for the second call.
Can anyone help us with this. We have multiple api's and all are happening twice which is actually increasing the load. And yes we have researched it.
Router.js
angular.module('adminsuite',['ngFileUpload','ui.router','ngCookies','angular-clipboard','ngAnimate', 'ngSanitize', 'ui.bootstrap','ngMessages']).constant("__env",env).config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/');
//$locationProvider.html5Mode(true);
$stateProvider
.state('login', {
url: '/',
views:{
header:{
templateUrl: '',
controller: ''
},
pageContent:{
templateUrl: 'Login/login3.html',
controller: 'loginController'
},
footer:{
templateUrl: 'common/footer3.html',
controller: 'footerController'
}
}
})
// HOME STATES AND NESTED VIEWS ========================================
.state('dashboard', {
url: '/dashboard',
views:{
header:{
templateUrl: 'common/header.html',
controller: 'headerController'
},
pageContent:{
templateUrl: 'dashboard/dashboard.html',
controller: 'dashboardController'
},
footer:{
templateUrl: 'common/innerFooter.html',
controller: 'footerController'
}
}
})
//SURVEY STATES
.state('survey', {
url: '/survey',
views:{
header:{
templateUrl: 'common/headerTool.html',
controller: 'headerController'
},
pageContent:{
templateUrl: 'survey/survey.html',
controller: 'surveyController'
},
footer:{
templateUrl: 'common/innerFooter.html',
controller: ''
}
}
});
// ABOUT PAGE AND MULTIPLE NAMED VIEWS =================================
})
LoginAuthenticationService.js
UserService.GetByUsername(requestData)
.then(function (user) {
console.log(user);
if (user.SessionID) {
sessionID = user.SessionID;
userDetails = user.UserProfile;
response = { success: true};
} else {
response = { success: false, message: 'Username or password is incorrect' };
}
callback(response);
});
UserService.js
function GetByUsername(user) {
//console.log(__env.apiUrl);
return $http.post(__env.apiUrl+'/UserAuthentication/login', user, {headers: { 'Content-Type': 'application/json'}}).then(handleSuccess, handleError('Error getting user by username'));
}
Api.js
$http.get(__env.apiUrl+'/UserSurvey/GetAllSurveys', {
headers: { 'Content-Type': 'application/json','SessionID':$rootScope.token}
})
.then(function(response){
console.log(response);
return response.data;
}, function(error){
console.log("error");
console.log(error);
return error;
});
Any help appreciated.
Assuming, you have declared controllers within your application using AngularUI state definitions such as the following:
$stateProvider
.state('index',
{
url : '/',
templateUrl : 'templates/home.html',
controller : 'HomeController'
})
And then, in the home.html view template, you also declare the controller using the ng-controller directive like so:
<div ng-controller="HomeController">
Then you have, without realising it, attached the controller twice (once through the state definition and twice through the ng-controller directive) which causes the code contained within the controller to execute twice as well.
You might be having a digest cycle issue.
When my AJAX module is located in plain Javascript my data renders on the first server query. However, when I place my AJAX module in an AngularJS module I must query the server twice before my data renders. Note the query is invoked from the UI.
After poking around I realized the data had indeed arrived on the first query and was assigned to all designated objects and variables but only within the scope of the AngularJS code. Of course, the data had arrived asynchronously and the UI had already gone through a digest cycle and had no reason to go again because nothing in the UI had changed. When there’s a change in the UI Angular updates everything but does nothing when the change (arriving data) comes from the server.
Subsequently, the second identical query would force a digest cycle and update all the bindings with the data that was already sitting there from the first query.
Thus the objective is to force a digest cycle from Javascript to update your UI bindings. I now force a digest cycle at the end of my callback function.
To force a digest cycle place the Angular method $scope.$apply([exp]) after your data variable assignments are complete. I found helpful details in the Angular docs at: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply and also a great explanation with working examples at: http://jimhoskins.com/2012/12/17/angularjs-and-apply.html and an important detail about using the “controller as” syntax when forcing a digest cycle at: How to call $scope.$apply() using "controller as" syntax and hopefully this fixes the problem of the double HTTP call.
I like the ability for Angular's router to 'resolve' data for me before transferring control to a controller. How can I show something to the user (spinner, "loading...", etc.) while waiting for a route's resolve function to complete, in the case of an ajax call getting run for the resolve function?
Here's an example from a router that shows what I mean:
.when('/users/:userId/profile', {
templateUrl: 'views/profile.html',
controller: 'ProfileCtrl',
resolve: {
userProfile: ['$route', 'ProfileService', function ($route, ProfileService) {
return ProfileService.loadProfile($route.current.params.userId);
}]
}
})
As I understand it, "ProfileCtrl" does not get created until "userProfile" has been resolved. That means I can't put code there to run while waiting for the resolve function to complete. In my case "ProfileService.loadProfile" makes and HTTP request, so for the sake of this example, let's say it takes a few seconds to return.
What's the recommended way to show something to the user while waiting for this?
You can use $routeChangeStart and $routeChangeSuccess to set some boolean that is used to display a loading animation or whatever in your view:
angular.module('myApp').run(function($rootScope) {
$rootScope.$on('$routeChangeStart', function() {
$rootScope.isLoading = true;
})
$rootScope.$on('$routeChangeSuccess', function() {
$rootScope.isLoading = false;
})
})
in your template you'd have something like:
<div class='loading' ng-show='isLoading'></div>
Or since that is linked to a template which may or may not be available, put class on the page body:
<body ng-class='loading: isLoading'>
</body>
and style it however you like.
As per https://docs.angularjs.org/api/ngRoute/service/$route 'Once all of the dependencies are resolved $routeChangeSuccess is fired.' There is also routeChangeError if you want to tell users when there is a problem with your ajax/resolve. ui-router has analogous stateChangeStart etc.
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
}
I have a situation where the Angular $routeProvider appears to not fire controller actions on route changes.
The routes are super simple urls:
window.app = angular.module('app', ['ngRoute', 'app.filters', 'app.services', 'app.directives', 'app.controllers'])
.config([
'$routeProvider', function($routeProvider) {
console.log("app.js config launched");
$routeProvider
.when('/nav', {
templateUrl: 'temp/test.html',
controller: 'navController'
// controller: function($scope) { alert('scope called.') }
})
.when('/home', {
controller: 'homeController',
template: ' '
});
$routeProvider.otherwise({ redirectTo: '/home' });
}
]);
The controller is just an log out to verify access:
app.controller('navController', [
"$scope", "cellService",
function ($scope, cellService) {
console.log("**** navController fired");
}
]);
The initialization code fires so the routing is initialized. When I hit:
http://localhost:4333/app/#/nav
and the url changes I can see that the test.html template is accessed by the browser, but the controller never fires.
This seems to indicate the route is getting activated by the URL change, but for some reason the controller is not firing. I've tried using a function instead of a controller name, but that too never gets fired. I've also verified that the controller is valid by attaching ng-controller="navController" to an element and that fires the controller just fine.
This is a page that originally didn't have routing associated as it was basically single self-contained page that didn't need navigation. I added the route code after the fact. I added an ng-view (there wasn't one before) after which at least the template started loading - without ng-view nothing happens.
Stumped and not sure what else to look at. Help.
It turns out the problem really was operator error on my part, but I think it's a scenario that can cause issues so I'll use this as the answer.
The issue that caused this problem were two-fold:
The HTML template HTML page (via templateUrl) had an invalid URL so the page never loaded
and the controller wasn't fired because of that.
When switching to a template I used an empty template (" ") but had also
removed the ng-View directive. The ng-View directive MUST BE present
even when using an empty template. Without it the controller doesn't fire.
In both cases it didn't work and I mistakenly assumed that the controller was not getting fired which was confusing because it did fire if I explicitly hooked it up with ng-controller.
Yup plain operator error, but the latter is vitally important - without ng-View the controller doesn't fire.
What happens if you define the function externally and reference that? So instead of
.when('/nav', {
templateUrl: 'temp/test.html',
controller: 'navController'
})
It would be
.when('/nav', {
templateUrl: 'temp/test.html',
controller: navController
})
and elsewhere
function navController($scope, cellService){
console.log("**** navController fired");
}
navController.$inject = ['$scope', 'cellService'];
In the route definition below if I go to #/systemadmin/edit/Testing it brings up the SystemAdminController but not the one defined in the child route I am using. I am missing something.
$stateProvider.state('systemadmin', { url: '/systemadmin', controller: 'SystemAdminController', templateUrl: 'app/templates/SystemAdmin.html?v=' + dl.buildDate })
.state('systemadmin.edituser', { url: '/edit/:selectedUser', controller: function ($scope, $stateParams) { debugger; }, templateUrl: 'app/templates/SystemAdmin.html?v=' + dl.buildDate });
A couple of things:
Your child state controller is missing a $scope, all controllers need an $scope in angular.
When you go to edituser, the systemadmin controller will also execute, as well as the edituser controller.
EDIT
Also, you need to define your parameter with curly braces in your route definitions, not with colons, that's ng-route syntax not ui.router:
{ url: '/edit/{selectedUser}' }
Another thing which is suspect you may be missing out, as I have many times, is that the view of your parent state needs to have a ui-view itself, see this working plunk.