Angular ui router change state with query params - javascript

How i can go to a state and add query params to the url at the same time?
Lets say i have this state:
$stateProvider
.state('cart', {
templateUrl: 'client/cart/cart.html',
url: '/my-cart',
controller: 'CartController'
})
I want from some views to $state.go('cart') and from some views to $state.go('cart') but with query params added to it like, /cart?purchase=complete

So i found the answer, i hope it will help for someone else.
$stateProvider
.state('cart', {
templateUrl: 'client/cart/cart.html',
url: '/my-cart?purchase',
controller: 'CartController'
});
And then:
$state.go('cart', {'purchase': 'complete'});
The results will be:
my-cart?purchase=complete

try this
$state.go('cart', {'purchase': 'complete'});

Related

AngularJS - $stateProvider when user put wrong URL

I'm new angularjs student.
I'm using state provider in my project, i don't want to change this. Because the code is done.
Here is my code:
function config($stateProvider, $urlRouterProvider) {
$urlRouterProvider
.when('/SecondMain', '/SecondMain/OtherPageOne')
.when('/Main', '/Main/PageOne')
.otherwise("/notfound")
$stateProvider
.state('Main', {
abstract: true,
url: "/Main",
templateUrl: "/templates/Common/Main.html"
})
.state('SecondMain', {
abstract: true,
url: "/SecondMain",
templateUrl: "/templates/Common/SecondMain.html"
})
.state('notfound', {
url: "/NotFound",
templateUrl: "/templates/Common/NotFound.html"
})
.state('Main.PageOne', {
url: "/Main/PageOne",
templateUrl: "/templates/Main/PageOne.html"
})
.state('Main.PageTwo', {
url: "/Main/PageTwo",
templateUrl: "/templates/Main/PageTwo.html"
})
.state('SecondMain.OtherPageOne', {
url: "/SecondMain/PageOne",
templateUrl: "/templates/SecondMain/OtherPageOne.html"
})
.state('SecondMain.OtherPageTwo', {
url: "/SecondMain/PageTwo",
templateUrl: "/templates/SecondMain/OtherPageTwo.html"
})
angular
.module('inspinia')
.config(config)
.run(function ($rootScope, $state) {
$rootScope.$state = $state;
});
}
I want a logic like this: If the user put:
/Main/PageThree
This page does not exist, but the user start URL with
/Main
so that he need to go to -> /Main/PageOne
if the user put:
/Ma/PageOne
/Ma does not exist, the user starts URL totally wrong, so that he goes to -> /Notfound Basically if the user put /Main/WRONG_LINK, he go to /Main/PageOne . And if he does not start with /Main, he go to NotFound.
Can anyone help me please?
Thanks a lot!!!
You are missing this configuration
$urlRouterProvider.otherwise('/NotFound');
Just add this line if no matching route is found then it will redirect you to the /NotFound url
This answer is inspired by this answer.
First of all, you will have to make the Main state non-abstract, so that it can be visited. Then, you can write config related to where you want to redirect (for example, I've used redirectTo with the state):
$stateProvider
.state('Main', {
redirectTo: "Main.PageOne",
url: "/Main",
templateUrl: "/templates/Common/Main.html"
})
// ... Rest of code
So, whenever the URL is changed to /Main, this state will get activated. The second config will be to create a listener for $stateChangeStart event as follows:
angular
.module('inspinia')
.config(config)
.run(function ($rootScope, $state) {
$rootScope.$on('$stateChangeStart', function(evt, to, params) {
if (to.redirectTo) {
evt.preventDefault();
$state.go(to.redirectTo, params, { location: 'replace' })
}
});
});
Now, if a URL like /Ma/* is hit, it automatically be redirected to /NotFound. And if a URL like /Main is hit, it will redirect to /Main/PageOne.
You can follow up on further discussion on this link for any kind of troubleshooting.
Clearly read the statements below
Why are you using this line?
when('/Main', '/Main/PageOne')
For your redirection problem, have a look at the below state
.state('Main', {
abstract: true,
url: "/Main",
templateUrl: "/templates/Common/Main.html"
})
abstract: true ==> This denotes that this particular state is an abstract which can never be activated without its child.
SOURCE: ui-router js code. Refer the below snippet
Since you have this main state as abstract, you are redirected to the otherwise.
Hope this

UI-router empty param causes navigation to wrong route

This should be simple but I just can't figure it out.
I have two routes:
$stateProvider
.state('users', {
url: '/users',
views: {'#': {
templateUrl: 'templates/users.tpl.html',
controller: 'UsersCtrl as users'
}}
})
.state('users.edit', {
url: '/{userId}',
views: {'#': {
templateUrl: 'templates/editUser.tpl.html',
controller: 'EditUserCtrl as editUser'
}}
});
This works fine if you use a ui-sref or $state.go to navigate to the "users" state by name, but if you type domain.com/users/ into the URL bar it goes to the edit state with empty userId parameter even though there is nothing after the trailing stash.
Normally this wouldn't be a problem but firing the editUser route with no userId causes console errors which would be a pain to fix.
Is this easily fixable?
Take a look to this post:
https://github.com/angular-ui/ui-router/issues/50
and this link referenced in the post:
https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-make-a-trailing-slash-optional-for-all-routes
Your states definition should be
$stateProvider
.state('users', {
url: '/users',
views: {'#': {
templateUrl: 'templates/users.tpl.html',
controller: 'UsersCtrl as users'
}}
})
.state('users.edit', {
url: '/edit/{userId}',
views: {'#': {
templateUrl: 'templates/editUser.tpl.html',
controller: 'EditUserCtrl as editUser'
}}
});
your child state url should be '/edit/{userId}'. When we create a child state its url automatically added its parent state url. So if your url is '/{userId}' it will be 'domain.com/users/{userId}'. That's why for domain.com/users/ its navigate to the state users.edit with null parameter value.
https://github.com/angular-ui/ui-router/wiki/nested-states-%26-nested-views

How to deal with specific route state url parameters on AngularJS or Ionic? How to do route state override on specific parameters?

My question is simple, but I couldn't find solution anywhere else.
For example I have a normal route state with parameter,
.state('page', {
url: '/page/:pageid',
templateUrl: 'templates/pages.html',
controller: 'pagesCtrl'
})
However for example, if I have 1000 pages, but for the Number 1 and Number 999 pages I have to use another template. How could I simply do this? Something like
.state('page', {
url: '/page/:pageid',
templateUrl: 'templates/pages.html',
controller: 'pagesCtrl'
})
.state('page', {
url: '/page/1',
templateUrl: 'templates/page1.html',
controller: 'pagesCtrl'
})
.state('page', {
url: '/page/999',
templateUrl: 'templates/page999.html',
controller: 'pagesCtrl'
})
Will this work?I tested, the later 2 options are not overriding the original state with parameter.
If I wish to use the same controller, how to load the 1 and the 999 as the pageid parameter in the controller?
Definitely you shouldn't have two more state for separate template. You should use single generic state which will take templateUrl with the help of passed state parameter.
Code
.state('page', {
url: '/page/:id',
templateUrl: function($stateParams){
var template = $stateParams.id.indexOf([1, 1000]) > -1?'pages.html'
:'page'+$stateParams.id+'.html';
return 'templates/'+template ,
}
controller: 'pagesCtrl'
})

Child state loads parent state templateUrl in nested routes of UI-Router

I'm using UI-Router module for routing. I have 2 states that router should match the urls with them according to nested routes laws :
// Dashboard
.state('dashboard', {
url: "/dashboard",
templateUrl: "dashboard/views/index.html",
controller: "DashboardController",
...
})
// Users
.state('users', {
url: "/users",
templateUrl: "users/views/index.html",
controller: "UsersController",
...
})
// Single User
.state('users.id', {
url: "/{id:(?:[a-z0-9_-]{3,16})}",
templateUrl: "users/views/show.html",
controller: "UserController",
...
})
also I have set a default route :
$urlRouterProvider.otherwise("/dashboard");
Problem :
when I go to http://127.0.0.1:8000/app/#/users/testuser123, it shows index.html from users state instead of show.html from users.id state. What's the Problem ?
You should add users within your url definition for users.id if you call http://127.0.0.1:8000/app/#/users/testuser123
.state('users.id', {
url: "/users/{id:(?:[a-z0-9_-]{3,16})}",
templateUrl: "users/views/show.html",
controller: "UserController",
...
})

opening a modal in a route in AngularJS with angular-ui-bootstrap

I am trying to do what was essentially answered here Unable to open bootstrap modal window as a route
Yet my solution just will not work. I get an error
Error: [$injector:unpr] Unknown provider: $modalProvider <- $modal
My app has the ui.bootstrap module injected - here is my application config
var app = angular.module('app', ['ui.router', 'ui.bootstrap','ui.bootstrap.tpls', 'app.filters', 'app.services', 'app.directives', 'app.controllers'])
// Gets executed during the provider registrations and configuration phase. Only providers and constants can be
// injected here. This is to prevent accidental instantiation of services before they have been fully configured.
.config(['$stateProvider', '$locationProvider', function ($stateProvider, $locationProvider) {
// UI States, URL Routing & Mapping. For more info see: https://github.com/angular-ui/ui-router
// ------------------------------------------------------------------------------------------------------------
$stateProvider
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
.state('transactions', {
url: '/transactions',
templateUrl: '/views/transactions',
controller: 'TransactionsCtrl'
})
.state('login', {
url: "/login",
templateUrl: '/views/login',
controller: 'LoginCtrl'
})
.state('otherwise', {
url: '*path',
templateUrl: '/views/404',
controller: 'Error404Ctrl'
});
$locationProvider.html5Mode(true);
}])
I have reduced my controller to the following:
appControllers.controller('LoginCtrl', ['$scope', '$modal', function($scope, $modal) {
$modal.open({templateUrl:'modal.html'});
}]);
Ultimately, what I am hoping to achieve is when login is required not actually GO to the login page, but bring up a dialog.
I have also tried using the onEnter function in the ui-router state method. Couldn't get this working either.
Any ideas?
UPDATE
Ok - so as it turns out, having both ui-bootstrap.js AND ui-bootstrap-tpls breaks this - After reading the docs I thought you needed the templates to work WITH the ui-bootstrap. though it seems all the plunkers only load in the ..tpls file - once I removed the ui-bootstrap file my modal works...Am i blind? or doesn't it not really say which one you need in the docs on github? -
Now i just need to figure out how to prevent my url from actually going to /login, rather than just show the modal :)
update 2
Ok, so by calling $state.go('login') in a service does this for me.
Hi I had a hard time getting through the similar problem.
However, I was able to resolve it.
This is what you would probably need.
app.config(function($stateProvider) {
$stateProvider.state("managerState", {
url: "/ManagerRecord",
controller: "myController",
templateUrl: 'index.html'
})
.state("employeeState", {
url: "empRecords",
parent: "managerState",
params: {
empId: 0
},
onEnter: [
"$modal",
function($modal) {
$modal.open({
controller: "EmpDetailsController",
controllerAs: "empDetails",
templateUrl: 'empDetails.html',
size: 'sm'
}).result.finally(function() {
$stateProvider.go('^');
});
}
]
});
});
Click here for plunker. Hope it helps.
I'm working on something similar and this is my solution.
HTML code
<a ui-sref="home.modal({path: 'login'})" class="btn btn-default" ng-click="openModal()">Login</a>
State configuration
$stateProvider
// assuming we want to open the modal on home page
.state('home', {
url: '/',
templateUrl: '/views/index',
controller: 'HomeCtrl'
})
// create a nested state
.state('home.modal', {
url: ':path/'
});
Home controller
//... other code
$scope.openModal = function(){
$modal.open({
templateUrl: 'path/to/page.html',
resolve: {
newPath: function(){
return 'home'
},
oldPath: function(){
return 'home.modal'
}
},
controller: 'ModalInstanceController'
});
};
//... other code
Finally, the modal instance controller.
This controller synchronizes the modal events (open/close) with URL path changes.
angular.module("app").controller('ModalInstanceController', function($scope, $modalInstance, $state, newPath, oldPath) {
$modalInstance.opened.then(function(){
$state.go(newPath);
});
$modalInstance.result.then(null,function(){
$state.go(oldPath);
});
$scope.$on('$stateChangeSuccess', function () {
if($state.current.name != newPath){
$modalInstance.dismiss('cancel')
}
});
});
You may create a state with the same templateUrl and controller as your page where you want to show the modal, adding params object to it
$stateProvider
.state('root.start-page', {
url: '/',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl'
})
.state('root.login', {
url: '/login',
templateUrl: 'App/src/pages/start-page/start-page.html',
controller: 'StartPageCtrl',
params: {
openLoginModal: true
}
})
And in controller of the page, use this parameter to open the modal
.controller("StartPageCtrl", function($scope, $stateParams) {
if ($stateParams.openLoginModal) {
$scope.openLoginModal();
}
I found a handy hint to get this working. There are probably caveats, but it works for me. You can pass a result still but I have no need for one.
Using finally instead of the then promise resolve sorted this for me. I also had to store the previous state on rootScope so we knew what to go back to.
Save previous state to $rootScope
$rootScope.previousState = 'home';
$rootScope.$on('$stateChangeSuccess', function(ev, to, toParams, from, fromParams){
$rootScope.previousState = from.name;
})
State using onEnter
$stateProvider.state('contact', {
url: '/contact',
onEnter: function ($state, $modal, $rootScope){
$modal.open({
templateUrl: 'views/contact.html',
controller: 'ContactCtrl'
}).result.finally(function(){
$state.go($rootScope.previousState);
})
}
});

Categories

Resources