I would like to be able to access the url parameters in my run function and make actions based on those params. However, I was pretty surprised to see that ui.router's $stateParams object is empty in my run function.
angular.module('app', ['ui.router'])
.run(['$rootScope', '$state', '$stateParams', '$location', function($rootScope, $state, $stateParams, $location) {
$rootScope.$state = $state;
$rootScope.location = $location;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('$stateChangeStart', function(event, toState) {
if (toState.name === 'main') {
event.preventDefault();
$state.go('main.child', {
param: 1
})
}
});
console.log('$stateParams is empty!');
console.log($stateParams);
console.log($rootScope.$stateParams);
}])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state('main', {
url: '',
template: '<div>hey</div><div ui-view></div>'
})
.state('main.child', {
url: '/:param',
template: 'child state template'
});
}]);
Is it possible to access the params accessed from $stateParams in the run function? Or are they only available in the config function? Why are they not accessible in the run function?
Plnkr: http://plnkr.co/edit/1YXKRmR48LyxbGXWq66Y?p=preview
Thanks for any help.
It looks like you are using StateChangeStart event and you can access parameters in this event:
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
//you code goes here
console.log(toParams);
}
I am using it to add some custom logic to parametrs (authentication redirects)
Related
I keep seeing examples on this but I don't know what I am doing wrong.
I load an item and its content into ng-view. When I refresh the page, it disappears. I have passed a parameter to the URL of the state and I am lost what to do next.
People have talked about $stateParams which I can log from my controller and I can see that item with id: 3 has been selected.
How do I keep the view populated with this item even on refresh? An example with my code would be greatly appreciated.
var app = angular.module('myApp', ['ngRoute', 'ui.router']);
app.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', '$routeProvider', function($stateProvider, $locationProvider, $urlRouterProvider, $routeProvider) {
$urlRouterProvider
.otherwise('/patents');
$stateProvider
.state("patents", {
url: "/patents",
templateUrl: "templates/patents/list/list-patents.htm",
controller: "patentListCtrl",
})
.state("patents.item", {
url: "/:id",
templateUrl: function() {
//THIS IS WHERE I AM NOT SURE HOW TO PASS THE URL THE ID
},
controller: "patentItemCtrl"
})
}]);
app.controller('patentItemCtrl', ['$scope', 'patentTabService','$stateParams', '$state', '$routeParams', function($scope, patentTabFactory, $stateParams, $routeParams){
console.log($stateParams.id)
}])
You should be able to to retrieve the required data by making a call your data service and then assign to your view. In your case call patentTabService to get patent with the id and then load that patent object into your view. For example, note I am assuming you already have some way to get a patent by id in your service:
app.controller('patentItemCtrl', ['$scope', 'patentTabService','$stateParams', '$state', '$routeParams', function($scope, patentTabFactory, $stateParams, $routeParams){
$scope.patent = {};
if (Number.isInteger($stateParams.id) ){
$scope.patent = patentTabFactory.getPatent($stateParams.id);
}
console.log($stateParams.id)
}])
So I am using Ionic and the Ionic Authentication with this code:
.controller('newEntryCtrl', ['$scope', '$stateParams', '$ionicAuth', '$state',
function ($scope, $stateParams, $ionicAuth, $state) {
if ($ionicAuth.isAuthenticated()) {
$state.go('login');
}
}])
That code works and I have lots of controllers. Is there a way to just inject a factory and never do if else in my controller already?
Write Authentication in run.
.run(['$rootScope', '$ionicAuth', '$state',
function ($rootScope, $ionicAuth, $state) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
if ($ionicAuth.isAuthenticated()) {
$state.go('login');
}
});
}
]);
I am following the angularfire tutorial to authenticate users.
Users are able to register, signin and even signout in the app.
When I try to use a resolve to check for $requireSignIn() for some routes(ui-route), it doesn't work.
Also, I want to do a check for user authentication status($onAuthStateChanged()) in my app.js where my modules are loaded. Then if there is a change in authentication, update authentication service( userAuth). I am using ng-show="authData" / ng-hide="authData to change html for logged in elements. But sometimes even after login, some of these elements are still showing as not logged in. I think this has something to do with the authentication update status.
If a user is logged in and the try to visit the login/signup page send them back to home page.
Here is my app.js
angular
.module('myApp', [
'ngAnimate',
'ngAria',
'ngCookies',
'ngResource',
'ui.router',
'ngMeta',
'firebase'
])
.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
if (error === "AUTH_REQUIRED") {
$state.go("home");
}
});
}])
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
function( $stateProvider, $urlRouterProvider, $locationProvider, ngMetaProvider, $location, userAuth) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('/', {
url: '/',
templateUrl: 'views/main.html',
controller: 'MainCtrl',
meta: {
'title': 'Goaf | Your next great destination',
'description': 'This is the description shown in Google search results'
}
})
.state('home', {
url: '/home',
templateUrl: 'views/home.html',
controller: 'HomeCtrl',
meta: {
'title': 'Goaf | Your next great destination',
'description': 'This is the description shown in Google search results'
},
resolve: {
"currentAuth": ["userAuth", function(userAuth) {
return userAuth.$requireSignIn();
}]
}
})
}]);
Here is the controller for the home page where I want only logged in users:
angular.module('myApp')
.controller('HomeCtrl', ["currentAuth", function ($rootScope, $scope, $http, $interval, $location, userAuth, dataservice, currentAuth) {
$scope.authData = userAuth.isLoggedIn();
}]);
And here is my userAuth service file:
angular.module('myApp')
.service('userAuth', ["$firebaseAuth", function($firebaseAuth) {
var firebaseAuthObject = $firebaseAuth();
this.login = function(loginEmail, loginPassword){
return firebaseAuthObject.$signInWithEmailAndPassword(loginEmail, loginPassword);
};
this.isLoggedIn = function(){
return firebaseAuthObject.$getAuth();
};
this.signOutUser = function() {
firebaseAuthObject.$signOut();
console.log('logging out user!');
};
}
]);
I have a single-page application built in angularjs, using UI-Router and nested views. My code looks like this:
app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider' ,'$mdDateLocaleProvider', '$locationProvider', function ($stateProvider, $urlRouterProvider, $httpProvider, $mdDateLocaleProvider, $locationProvider) {
var rootpath = config.paths.components;
$stateProvider.state('home', {
url: '/',
views: {
index: {
templateUrl: rootpath + '_root/template.html',
controller: "RootController"
},
"header#home": {
templateUrl: rootpath + 'header/header-template.html',
controller: "HeaderController"
},
"sidebar#home": {
templateUrl: rootpath + 'sidebar/sidebar-template.html',
controller: "SidebarController"
},
"main#home": {
templateUrl: rootpath + 'main/main-template.html',
controller: "MainController"
}
},
resolve: {
authorize: ['RootService', function (RootService) {
var auth = RootService.getKey();
return RootService.getConfig(auth.key);
}]
},
});
$urlRouterProvider.otherwise('/');
}]).run(['$rootScope', '$state', '$window', function($rootScope, $state, $window){
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error){
$window.location = error.status +'.html';
});
In the "home" state, I'm doing a resolve to see if the authentication key passed in is valid.
If the key is invalid or has expired, $stateChangeError event catches the error and redirects the user to an error page.
This works fine when the application starts and on refresh.
Problem is, when the key has expired (only valid for ten minutes) and the application is not reloded, the
$stateChangeError event doesn't catch the error message.
Any thoughts on how to fix this?
You can solve this problem by using the $watch provided by the angular js.
$scope.$watch(function(scope) { return scope.data.myVar },
function() {}
);
The first function is the value function and the second function is the listener function.
This example value function returns the $scope variable scope.data.myVar. If the value of this variable changes, a different value will be returned, and AngularJS will call the listener function.
I think this might solve your problem...
After refreshing the page, the state changes back to login. I am using $sessionStorage to store the data and I am able to print them successfully after login, but when I refresh the page, my page should stay on dashboard.html but routes to login state.
angular.module('App', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngSanitize',
'ngAnimate',
'ngTouch',
'ui.bootstrap',
'ui.router',
'toaster',
'ngStorage'
])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl: "views/login.html"
})
.state('dashboard', {
url: '/dashboard',
templateUrl: "views/dashboard.html",
required: true
});
$urlRouterProvider.otherwise('/login');
})
.run(["$rootScope", "$state", "$location", "authService", "$cookies", "$sessionStorage", function ($rootscope, $state, $location, authService, $cookies, $sessionStorage) {
$rootscope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
if (toState.required && !$sessionStorage.authuserid) {
alert("state not authenticated");
e.preventDefault();
$state.go('login');
}
});
}]);
Here is my controller:
angular.module('App')
.controller('loginController', ['$scope', '$http', '$timeout', '$location', '$rootScope', 'AUTHEVENTS', 'authService', '$cookies', '$state', 'userManagementFactory', '$localStorage', '$sessionStorage', function ($scope, $http, $timeout, $location, $rootScope, AUTHEVENTS, authService, $cookies, $state, userManagementFactory, $localStorage, $sessionStorage) {
$scope.login = function () {
authService.login(data).then(function (response) {
$rootScope.$broadcast(AUTHEVENTS.loginSuccess);
console.log("response data is: ", response);
$sessionStorage.auth = response;
$sessionStorage.authname = response.data.name;
$sessionStorage.authrole = response.data.roles[0].name;
$sessionStorage.authuserid = response.data.user_id;
$sessionStorage.authprofilepic = response.data.profile_picture;
if ($sessionStorage.authuserid) {
$state.go('dashboard');
} else {
alert('user not authenticated');
}
}, function (error) {
$scope.responseMessage = error.data.error;
$rootScope.$broadcast(AUTHEVENTS.loginFailed);
}
)
}
}])
Html:
<div ng-controller="loginController">
<header class="main-header" ng-include src="'views/header.html'"></header><!--/main top header -->
<div ui-view></div>
</div>
I am not sure what is causing it to change route on page refresh?
StateConfig doesnt seem to accept 'required' field, please refer https://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$stateProvider
Instead you should have
.state('dashboard', {
url: '/dashboard',
templateUrl: "views/dashboard.html",
data: {
required: true
}
});
and should check like this.
if (toState.data && toState.data.required && !$sessionStorage.authuserid) {
Try moving $urlRouterProvider.otherwise('/login'); before
`$stateProvider
.state('login', {
url: '/login',
templateUrl: "views/login.html"
})
.state('dashboard', {
url: '/dashboard',
templateUrl: "views/dashboard.html",
required: true
});`