cannot use a different controller with a view with ui-router AngularJS - javascript

I'm using ui-router for routing my angular app. I have the following route:
'use strict';
//Setting up route
angular.module('admins').config(['$stateProvider',
function($stateProvider) {
// Admins state routing
$stateProvider.
state('admin_home', {
url: '/admin',
templateUrl: 'modules/admins/views/list-admins.client.view.html'
}).
state('adduser', {
url: '/admin/create',
templateUrl: 'modules/admins/views/create-admin.client.view.html',
}).
state('viewAdmin', {
url: '/admins/:adminId',
templateUrl: 'modules/admins/views/view-admin.client.view.html'
}).
state('editAdmin', {
url: '/admins/:adminId/edit',
templateUrl: 'modules/admins/views/edit-admin.client.view.html'
});
}
]);
This is within my 'Admin' module, and that has its own controller (AdminsController).
However, I want to be able to create a new user from here, and the controller to do that is called 'AuthenticationController' and is elsewhere in the structure.
As far as I know, I should be able to put something like:
state('adduser', {
url: '/admin/create',
templateUrl: 'modules/admins/views/create-admin.client.view.html',
controller:'AuthenticationController'
})
and it should work.
However - I keep getting redirected back to the index page.
I suspect this may be because I'm using HTML5 and have this in my config also:
// use HTML 5
$locationProvider.html5Mode(true).hashPrefix('!');
//Sets the HTTP header type for the redirects
$httpProvider.defaults.headers.common = {
'Accept': 'application/json',
'Content-Type': 'application/json'
Can anyone help?

You should add :
$urlRouterProvider.otherwise("/home");
And declare your controller inside your state function (not in your view files) like that :
state('viewAdmin', {
url: '/admins/:adminId',
controller : AdminsController,
templateUrl: 'modules/admins/views/view-admin.client.view.html'
})
If it doesn't work, try to remove :
$locationProvider.html5Mode(true).hashPrefix('!');
//Sets the HTTP header type for the redirects
$httpProvider.defaults.headers.common = {
'Accept': 'application/json',
'Content-Type': 'application/json'
Let me know ;)

Related

three level nested url in angular

Here is my app.js
.state('dashboard', {
url: '/dashboard',
templateUrl : 'resources/components/dashboard/dashboard.html',
controller : 'dashboardController',
}).state('dashboard.profile', {
url: '/profile',
templateUrl : 'resources/components/clinicprofile/profile.html',
controller : 'profileController',
}).state('dashboard.setting', {
url: '/setting',
templateUrl : 'resources/components/setting/settings.html',
controller : 'profileController',
}).state('dashboard.setting.user', {
url: '/user',
templateUrl : 'resources/components/setting/user.html',
controller : 'profileController',
Note that my three level nested url is working fine when i am puttin ng-view in setting.html page
but i dont want to show the content of setting.html when a user is on
dashboard/setting/user
it is showing setting page content as well as user page content
i dont want to show the content of setting.html when a user is on user page
i want to show only user content on this url dashboard/setting/user how can i do that?
If you do not want the user page to be included in the settings page, it cannot be a child of settings, so a possible solution would be using an abstract state and changing the settings URL to something like setting/main:
.state('dashboard', {
url: '/dashboard',
templateUrl: 'resources/components/dashboard/dashboard.html',
controller: 'dashboardController',
}).state('dashboard.setting', {
abstract: true,
url: '/setting',
template: '<ui-view></ui-view>',
}).state('dashboard.setting.main', {
url: '/main',
templateUrl: 'resources/components/setting/settings.html',
controller: 'profileController',
}).state('dashboard.setting.user', {
url: '/user',
templateUrl : 'resources/components/setting/user.html',
controller : 'profileController',
})
UI Router documentation

RouteParams in AngularJS

I am trying to pass a routeParam to a $http.post in my Angular controller, but I dont seem to be passing the value correctly. Here is what I have below. Am an not using the $routeParams correctly? When using $scope.event_id = $routeParams.eventId; the partial page renders correctly with Event: {{event_id}} or Event: 5 for example.
I need the $http.post to be php/getItem.php?itemID=5
The HTML passing the event_id:
{{event.event_name}}
The routeProvider:
var pvApp = angular.module('pvApp', ['ngRoute']);
// configure our routes
pvApp.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'pages/home.html',
controller : 'mainController'
})
.when('/:eventId', {
templateUrl : 'pages/event_detail.html',
controller : 'eventController'
});
});
The Controller:
pvApp.controller('eventController', function($scope, $http, $routeParams) {
// $scope.event_id = $routeParams.eventId;
$http.post("php/getItem.php?itemID="+$routeParams.eventId).success(function(data){
$scope.items = data;
});
});
The Partial Page:
<div class="container">
<div class="row">
<div class="col-lg-12">
<h2>Event: {{event_id}}</h2>
</div>
</div>
</div>
first check
console.log($routeParams.eventId);
is print the event_id on the console correctly.
Then
Note that your using a POST request but your url like GET request.
change the request like below and try,
$http({
url: 'php/getItem.php',
method: "POST",
data: { itemID : $routeParams.eventId },
}).succes...
OR
$http.post('php/getItem.php', { itemID:$routeParams.eventId }).success...
here you can get the data in Php as,
$data = json_decode(file_get_contents("php://input"));
$data->itemID // to access name
OR
$http({
url: 'php/getItem.php',
method: "POST",
data: { itemID : $routeParams.eventId },
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
}).succes...
In Php,
$name= $_POST['itemID'];
may be this post will helps you.

Ionic controller not called after $state.go

I have a controller the get data from my back-end application when opening the state for the first time from the first controller it loads the data, but when it tries to open it again it does not load the new data
Here is how:
if (selectedServiceID == "000")
{
$state.go('balanceInquery');
};
Here is the called balanceInquery state controller:
.controller('BalanceInqueryController', function($scope, getAccountBalanceService, $state, $ionicLoading, $ionicPopup) {
getAccountBalanceService.get(username, pass, customerID, serviceAccID, langID)
.success(function(data) {
$scope.custBalance = data;
})
.error(function(data) {
var alertPopup = $ionicPopup.alert({
title: 'Error!',
template: 'Sorry something went wrong'
});
});
})
I had a similar problem. The first time was shown only after reload. The reason is view caching. Disable it with cache: false, like in my specific case:
$stateProvider
.state('login', {
url: '/login',
controller: 'LoginCtrl as vm',
templateUrl: 'app/login/login.html'
})
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html',
cache: false
})
This is due to view caching, which can be disabled in a variety of ways. See http://ionicframework.com/docs/nightly/api/directive/ionNavView/ for more details.

AngularJS: ui-router secured states

I have one main controller for my app - AppCtrl and use ui-router. How can I make secured states?
$rootScope.$on('$stateChangeStart',function(event, toState, toParams, fromState, fromParams){
var authorization = toState.data.authorization;
if(!Security.isAuthenticated() && authorization != false)
$location.path('/login');
});
For example I want to make books and authors states secured, and login state not secured.
.state('login', {
url: '/login',
templateUrl: /**/,
controller: /**/,
data: {
authorization: false
}
})
.state('books', {
url: '/books',
templateUrl: /**/,
controller: /**/,
data: {
authorization: true
}
})
.state('authors', {
url: '/authors',
templateUrl: /**/,
controller: /**/,
data: {
authorization: true
}
})
Security.isAuthenticated() function returns boolean. When I open /books everything works perfectly, page are being redirected to /login, when after redirecting I open /authors, page loads and it's content are shown, but browser's url is /login, so page being redirected, but somehow it's content are shown.
Figured out that I have to prevent opening next route, and go to login state. Made some changes and all works perfectly.
if (!Security.isAuthenticated() && authorization != false){
event.preventDefault();
$state.go('login');
}

AngularJS: Call a particular function before any partial page controllers

I want to call a particular function: GetSession() at the beginning of my application load. This function makes a $http call and get a session token: GlobalSessionToken from the server. This session token is then used in other controllers logic and fetch data from the server. I have call this GetSession()in main controller: MasterController in $routeChangeStart event but as its an asynchronous call, my code moves ahead to CustomerController before the $http response.
Here is my code:
var GlobalSessionToken = ''; //will get from server later
//Define an angular module for our app
var myApp = angular.module('myApp', ['ngRoute']);
//Define Routing for app
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/customer', {
templateUrl: 'partials/customer.html',
controller: 'CustomerController',
resolve: {
loadData: function($q){
return LoadData2($q,'home');
}
}
}).
otherwise({
redirectTo: '/home'
});
}]);
//controllers start here and are defined in their each JS file
var controllers = {};
//only master controller is defined in app.js, rest are in separate js files
controllers.MasterController = function($rootScope, $http){
$rootScope.$on('$routeChangeStart', function(){
if(GlobalSessionToken == ''){
GetSession();
}
console.log('START');
$rootScope.loadingView = true;
});
$rootScope.$on('$routeChangeError', function(){
console.log('ERROR');
$rootScope.loadingView = false;
});
};
controllers.CustomerController = function ($scope) {
if(GlobalSessionToken != ''){
//do something
}
}
//adding the controllers to myApp angularjs app
myApp.controller(controllers);
//controllers end here
function GetSession(){
$http({
url: GetSessionTokenWebMethod,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
}).success(function (data, status, headers, config) {
GlobalSessionToken = data;
}).error(function (data, status, headers, config) {
console.log(data);
});
}
And my HTML has following sections:
<body ng-app="myApp" ng-controller="MasterController">
<!--Placeholder for views-->
<div ng-view="">
</div>
</body>
How can I make sure this GetSession() is always called at the very beginning of my application start and before any other controller calls and also called only once.
EDIT: This is how I added run method as per Maxim's answer. Still need to figure out a way to wait till $http call returns before going ahead with controllers.
//Some initializing code before Angular invokes controllers
myApp.run(['$rootScope','$http', '$q', function($rootScope, $http, $q) {
return GetSession($http, $q);
}]);
function GetSession($http, $q){
var defer = $q.defer();
$http({
url: GetSessionTokenWebMethod,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
}).success(function (data, status, headers, config) {
GlobalSessionToken = data;
defer.resolve('done');
}).error(function (data, status, headers, config) {
console.log(data);
defer.reject();
});
return defer.promise;
}
Even though some of the solutions here are perfectly valid, resolve property of the routes definition is the way to go, in my opinion. Writing your app logic inside session.then in every controller is a bit too much , we're used such approach too in one of the projects and I didn't work so well.
The most effective way is to delay controller's instantiation with resolve, as it's a built-in solution. The only problem is that you have to add resolve property with similar code for every route definition, which leads to code duplication.
To solve this problem, you can modify your route definition objects in a helper function like this:
function withSession(routeConfig) {
routeConfig.resolve = routeConfig.resolve || {};
routeConfig.resolve.session = ['getSessionPromise', function(getSessionPromise) {
return getSessionPromise();
}]
return routeConfig;
}
And then, where define your routes like this:
$routeProvider.when('/example', withSession({
templateUrl: 'views/example.html',
controller: 'ExampleCtrl'
}));
This is one of the many solutions I've tried and liked the most since it's clean and DRY.
You can't postpone the initialisation of controllers.
You may put your controller code inside a Session promise callback:
myApp.factory( 'session', function GetSession($http, $q){
var defer = $q.defer();
$http({
url: GetSessionTokenWebMethod,
method: "POST",
data: "{}",
headers: { 'Content-Type': 'application/json' }
}).success(function (data, status, headers, config) {
GlobalSessionToken = data;
defer.resolve('done');
}).error(function (data, status, headers, config) {
console.log(data);
defer.reject();
});
return defer.promise;
} );
myApp.controller( 'ctrl', function($scope,session) {
session.then( function() {
//$scope.whatever ...
} );
} );
Alternative: If you don't want to use such callbacks, you could have your session request synchronous, but that would be a terrible thing to do.
You have not provided any details related to GetSession. For scenarios like this you should use the resolve property while defining your routes in $routeProvider. I see you are using resolve already.
What you can do now is to wrap the GlobalSessionToken into a Angular service like GlobalSessionTokenServiceand call it in the resolve to get the token before the route loads. Like
resolve: {
loadData: function($q){
return LoadData2($q,'home');
},
GlobalSessionToken: function(GlobalSessionTokenService) {
return GlobalSessionTokenService.getToken() //This should return promise
}
}
This can then be injected in your controller with
controllers.MasterController = function($rootScope, $http,GlobalSessionToken){

Categories

Resources