Change query param in url using UI-router - angularjs

Using ui-router how can I accomplish the following URL change? For example, when a user goes to "/page?hello=True" I want the url to change to "/page?status=hello".
$stateProvider.state('page', {
url: '/page/:id?status',
controller: 'MyCtrl as myCtrl',
templateProvider: function($templateCache) {
return $templateCache.get('templates/route.html');
}
});

You can use the stateChangeStart event in the app.run method to listen for state changes into that route, and change anything you want on the params. Something like this, might need to play with toState and toParams to get it right for you...
.run(['$state', '$rootScope', function($state, $rootScope) {
$rootScope.$on('$stateChangeStart', function(e, toState, toParams, fromState, fromParams) {
if (toState.name === 'invitation') {
//change toParams to whatever you want
}
});
});

Related

AngularJS controller middleware

I have an Angular endpoint like so:
$stateProvider.state("auth.signin", {
url: "/signin",
views: {
"auth-view#auth": {
templateUrl: "views/auth/signin.html",
controller: "SigninController"
}
}
});
I want a before filter (or a middleware) for my SigninController so if the user is already logged in, I want to redirect him to my HomeController.
In pseudo code, I'm looking for something like this:
$stateProvider.state("auth.signin", {
url: "/signin",
views: {
"auth-view#auth": {
templateUrl: "views/auth/signin.html",
controller: "SigninController"
}
},
before: () => {
if (User.loggedIn() === true) {
return $state.go("app.home");
}
}
});
I used similar features on alot of frameworks so I'm pretty certain Angular has something like this too. What's the Angular way of doing it?
Thank you.
Ps: I'm not using Angular 2 yet.
The ui router triggers a $stateChangeStart event, which you can capture:
app.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams, options) {
if (toState.name === "auth.signin" && userIsLoggedInLogicHere) {
event.preventDefault(); // prevent routing to the state
$state.transitionTo("app.home");
}
// else do nothing, it will just transition to the given state
})
}]);
See this documentation for reference

AngularJS - UI Router stateChangeSuccess event not firing

I am using UI Router in my angular app. I am trying to integrate state change events, but they are not firing on state change. Everything else is working fine and there is no error in console. I came across following similar questions, but none of the solution worked for me:
$rootScope.$on("$routeChangeSuccess) or $rootScope.$on("$stateChangeSuccess) does not work when using ui-router(AngularJS)
angular + ui-router: $stateChangeSuccess triggered on state b but not on a.b
Following is my Angular code:
(function() {
angular.module("bootdemo", [
"ngResource",
"ui.router",
"bootdemo.core",
"bootdemo.index"
])
.run(function ($rootScope, $location, $state, $stateParams) {
$rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){
alert("root change success");
})
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams, options){
alert("root change start");
})
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error){
alert("root change error");
})
})
.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state('index', {
url: "/",
templateUrl: '/index/templates/welcome.html',
controller: 'IndexController as vm'
})
.state('login', {
url: "/login",
templateUrl: '/index/templates/login.html',
controller: 'LoginController as ctrl'
})
.state('home', {
url: "/home",
templateUrl: '/index/templates/home.html',
controller: 'HomeController as ctrl'
})
});
}());
Left with no clue. I am not sure what I am missing.
StateChange events has been deprecated for ui.router >= 1.0
for the new ui.router use the following
StateChangeSuccess
$transitions.onSuccess({}, function() {
console.log("statechange success");
});
StateChangeStart
$transitions.onStart({}, function(trans) {
console.log("statechange start");
});
Check this migration guide for more information
If you are using the new ui-router (v1.0.0), the $stateChange* events will not work. You must use $transitions.on* hooks from now on.
You can read here.
https://ui-router.github.io/docs/latest/modules/ng1_state_events.html
https://github.com/angular-ui/ui-router/issues/2720
$state events are deprecated for angular version > 1.0.0.
now onward for change event we have to use $transitions
refer $transitions from here

Angular UI Router dynamic states on refresh goes to 404

I'm loading states dynamically based on the current user role. But when the page is refreshed it takes to the 404 page. Also in $stateChangeStart event fromState.name is blank.
Is there a way to go to the state before refresh button was clicked? Should I store the state before refresh is pressed and then use it?
.state('404', {
url: '/404',
templateUrl: '404.tmpl.html',
controller: function ($scope, $state, APP) {
$scope.app = APP;
$scope.goHome = function () {
$state.go('default.page');
};
}
})
$urlRouterProvider.otherwise('/404');
....
$rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
//fromState.name = '' on refresh
});
Thanks in advance!
The below seems to work, not sure if this is the best approach. On before unload event save the state, then use it in $stateChangeStart.
.run(function ($rootScope, $window, $state, authService, $http, $timeout, localStorageService) {
$rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
if (authService.isLoggedIn()) {
if (toState.name === "404" && fromState.name === '' && localStorageService.get("LAST_STATE") !== "404") {
authService.loadStates($stateProviderRef).then(function () {
$state.go(localStorageService.get("LAST_STATE"), localStorageService.get("LAST_STATE_PARAMS"));
});
}
}
});
window.onbeforeunload = function () {
localStorageService.set("LAST_STATE", $state.current.name);
localStorageService.set("LAST_STATE_PARAMS", $state.params);
return null;
}
})

UI-Router: Is it possible to change a query parameter while the state is loading?

I am wondering if it is possible to change query parameter in the ui-router while a state is still being loaded.
I was thinking along the following lines but this does not work...
$stateProvider
.state('foo',{
url:'/foo?bar',
templateUrl:'app/foo.html',
controller: 'fooController as foo',
resolve: {
Resource: function($state) {
return somepromise()
.then(function(baz) {
if (baz !== some condition) {
$state.params.bar = 'newValue';
return;
}
});
}
}
Any Suggestion? Thanks...
You can handle it inside the state declaration (I prefer this way)
.state('foo', {
url: "/foo?bar", // not sure if this kind of url can be used
template: "",
controller: ['$state', function ($state, $stateParams) {
if ($stateParams.bar == 'something') {
$state.go('bar');
}
}]
})
Or you can redirect when the state is starting to change using event defined in ui-route
Normally I put these things in HomeController
$rootScope.$on('$stateChangeStart',
function (event, toState, toParams, fromState, fromParams) {
//console.log("state change:", fromState.name, fromParams, toState.name, toParams);
if (toState.name == 'foo' && toParams.bar == 'something') {
$state.go('bar');
}
});
Do beware this might trigger an infinite loop if not handled correctly.

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