I have one exception to an otherwise dynamic route:
.state('item', {
abstract: true
})
// This is the 'hardcoded' static route
.state('item.static', {
url: '/static'
})
.state('item.content', {
url: '/:para'
})
As you can see the first child state has a fix url route. Then if the url is not exactly this fix word I want the routing to happen with child state 2.
It works when I first hit child state 1. However when I refresh the browser the views are not longer mapped and the ui-view stays empty. If I refeesh one of the dynamic routes it works.
I left out view and controller setup intentionally to make it look simpler.
Have you tried a regex pattern to rule out the "static" route for the para route? Theoretically, you should be able to use ruling out the "static" route and ui-router will pick up the dynamic route at that point.
Ui-Router Documentation
From Documentation:
// will only match a contactId of one to eight number characters
url: "/contacts/{contactId:[0-9]{1,8}}"
Related
When I navigate first to my index page where the url is '/', I want to display the content of the state '/matches'. What you think is better?
I can use
$urlRouterProvider.otherwise('/matches');
that works, but I know it's not a good solution.
So I have to choose between
1- redirecting / to /matches and I tried
$urlRouterProvider.when('/','/matches');
but it didn't work.
2- specify multiple paths / and /matches to the same state matches which I don't know how to do.
In ng-route I used to do it like this:
.when('/', {
redirectTo : '/matches'
})
but I don't think it's good to combine ng-route with ui-router.
I found a perfect solution
app.run(function($state){
$state.go('/matches');
});
Once the app runs, I call the state that I want to load using $state.go and I also kept the
$urlRouterProvider.otherwise('/matches');
in case the user tries to enter an invalid url (state), he will be redirected to the initial state.
I have an issue where I want to have a parameter on the route url e.g
$stateProvider.state('/someRoute', {
url: '/:path',
.....
});
$stateProvider.state('/contact', {
url: '/contact',
.....
});
But if I do that then other pages get misinterpreted as being part of this. for example /contact url thinks that "contact" is the param and not the page.
Is there a way around this or do I need to have a sub-page e.g /something/:path?
The issue is that currently due to the order of the states, your first state will capture all urls as it's expecting some parameter.
/contact satisfies the /:path criteria.
Either move the /:path as the last state. or create a /something/:path
Is it possible to configure ui-router in an Angular 1.5 application to completely ignore the address bar?
Desired behaviour is something like this:
Navigating between states via UI does not change the URL
Changing the URL does not cause navigation between states, only UI or programmatic actions do (clicking the buttons, etc.)
Hitting F5 restarts the application from "default" controller
Original URL (especially query parameters) must still be accessible
UPDATE: I am creating an application with a very specific use case, not a website. Ordinary web browsing practices do not apply here. Please accept the requirements as they are, even if it may seem to contradict common sense.
Agreed that the stated approach is not good if we consider classic web app.
I tried to create a sample application with your requirement in mind.
Here is how my router configuration(router.config.js) file looks like in my fruits app:
.state('start', {
url: '/',
templateUrl: '../app/start/start.html',
controller: 'startCtrl as vm',
})
.state('fruits', {
templateUrl: '../app/fruits/fruitshtml',
controller: 'fruitsCtrl as vm',
})
.state('fruits.details', {
params: {
fruitId: undefined
},
templateUrl: '../app/fruits/fruitdetails.html',
controller: 'fruitDetailsCtrl as vm'
})
Explanation of States:
start:
url / is entry point of my application. If url is /, start state will be loaded.
fruits:
This state shows list of fruits in my app. Note that there is no url defined for this state. So, if we go to this state, url won't change (State will change, but url won't).
fruits.details:
This state should show detail of a fruit with id fruitId. Notice we have passed fruitId in params. params is used to pass parameters without using the url! So, passing of parameters is sorted. I can write ui-sref="fruit.details({ fruitId: my-fruit-id })" to navigate to fruit.details state and show details of my fruit with fruitId my-fruit-id.
As you might have already got it, the main idea is to use states as means of navigation.
Does my app pass your points?
Navigating between states via UI does not change the URL
Changing the URL does not cause navigation between states, only UI or programmatic actions do (clicking the buttons, etc.)
Hitting F5 restarts the application from "default" controller
Original URL (especially query parameters) must still be accessible
->
pass: as we haven't defined url for states
pass: changing url will change to state to start. The app will not take user to any different state, but it does changes state to start or we could say our default state.
pass: refresh will take you to start state
pass: if you write start in your url, you app will got start state.
Possible work around for the 2nd point, which is not passed completely: We can write code to check the url (in startCtrl controller) passed. If url contains extra things appended to /start, go to previous state. If url is 'start' continue loading start page.
Update:
As pointed by OP #Impworks, solution for 2nd point is also passed if we set url of our start state to /. This way, if we append any string to url, the state won't change.
I am facing a url structure problem using ui-router in AngularJS. I want to have first level SEO friendly url structure like this:
https://people-profile.com/mike-david-tringe
So I can grab the SEO name "mike-david-tringe" via stateParam and use it to find data in database and populate the page.
The $stateProvider has code like this:
$stateProvider
.state('people', {
url: '/:nameUrl',
templateUrl: 'app/frontend/page.tmpl.html',
params: {
nameUrl: {squash: true},
},
controller: "PageController",
controllerAs: 'vm'
})
.state('admin', {
url:'/admin/:userId',
templateUrl:'app/frontend/admin/admin.html',
controller:'AdminController',
controllerAs: 'admin'
})
With above code, I can have https://people-profile.com/mike-david-tringe working with nameUrl = mike-david-tringe and I got SEO friendly first level url link. mike-david-tringe is SEO friendly and most important keywords beside the domain name.
But with this structure, https://people-profile.com/admin/ or https://people-profile.com/login/ will not work now. Since my controller try to grab admin as nameUrl and looking for data. And admin is not a nameUrl so my database will return null, the app will fail.
In short, stateParam nameUrl will grab anything after "/" so the url setting will think admin and login is :nameUrl but in fact, it is not.
So how do I structure my app ui-router structure to have SEO friendly url like https://people-profile.com/mike-david-tringe but when url is https://people-profile.com/admin/, it will load admin.html template and use AdminController instead as I defined in $stateProvider?
All you need to do is swap the order of them. The router will check in order of definition, so if /:nameUrl comes before /admin it will trigger first. But if you put /:nameUrl last then it will trigger on any url that hasn't already triggered something above.
A word of warning however. Moving between two urls that trigger the same state (like two urls that both hit /:nameUrl in your case) will not reload the controllers on the page. Only changing state will do that. There are options to change this behaviour, but it has always been very buggy for me.
how is it possible to set up url routes in the $stateProvider of the ui-router module with url params in a hierarchy like this
/home
/:username
/:title/editor
I only get it to work if there is no conflict on the same hierarchy level like:
/home
/user/:username
/editor/:title
Right now everything will router to /home if I try to set it up like in the first example.
I know it from other situations like on Google Appengine, where the first approach would work aswell and where it would be seen as a kind of hierarchy, where the /:username route would apply as long it not equals 'home'.
Thanks for help!
I would say this should be possible, e.g. this would work (see example):
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'test.html',
controller: 'TestCtrl',
})
.state('editor', {
url: '/:title/editor',
...
})
.state('user', {
url: '/:userName',
...
Observe it here. The reason why this is working, because the state editor - with a strong key /editor is evaluated before userName. The same for home - it is the first evaluated pattern.
BUT - I would suggest, do not count on order. Use these discriminators at the beginning (e.g. /user/... or /editor/..). Our users, will understand it as well, and any later confusion (why this url triggered that state) won't surprise us