ui-router url params with a hierarchy - angularjs

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

Related

Ionic Angular routeprovider not working

I'm working on an Ionic App where i run in some trouble.
I'm new to AngularJS and Ionic.
The user needs to be logged in to use the app. To check this an apicall to my server is called on entry of the app. If the user is not logged in, the app will show a modal where the user can login.
But in the small second that the apicall is made you see the "inside" of the app (restricted pages).
To avoid this i want to place a screen where the app checks if the user is logged in. And if the user is logged in, the screen needs to send the user further in the app.
The problem in this is that the app doesn't send the user on. I replaced all the code with a simple a href (ui-sref) but that doesn't work either.
The funny, weird part is that if i run it in my browser it works. But on my mobile(android) is doesn't do anything.
I tried it with a function with $location.path but i doesn't send me anywhere. It does set the path.
I tried $apply, $digest, $window.location.href .... etc etc. none worked.
If i don't use the wait screen everything works fine.
wait.html
<a ui-sref='app.proposals({"favorite" : 0})'>Continue</a>
RouteProvider
matcher.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider)
{
$ionicConfigProvider.tabs.position("bottom");
$ionicConfigProvider.tabs.style("standard");
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.state('app.proposals', {
url: '/proposals/:favorite',
views: {
'menuContent': {
templateUrl: 'templates/proposals.html',
controller: 'ProposalsCtrl'
}
}
})
.state('app.proposal', {
url: '/proposal/:title/:id/:url',
views: {
'menuContent' : {
templateUrl: 'templates/proposal.html',
controller: 'ProposalCtrl'
}
}
})
.state('wait',{
url: '/wait',
templateUrl: 'templates/wait.html',
controller: 'WaitCtrl'
});
// if none of the above states are matched, use this as the fallback
//$urlRouterProvider.otherwise('/app/proposals/0');
$urlRouterProvider.otherwise('/wait');
});
Alright, now, the best way to solve this would be use a better practice. Your application follows the standard Authentication Flow. Now, according to me, wouldn't it be better if you just animate the current view in context. This will serve two purposes
reduce the render-load time;
get rid of you problem.
According to me, the problem here is that when you make the API call, Ionic tries to get hold of a cached page. The best way to fix it to have a default base check; point to index.html, the IndexController checks is the user is logged in, if it is, use $state.go("STATE_NAME") to go to the logged in state, otherwise, go to a state where you login.
Trust me when I say this: not only will this be easier, it'll also be more maintainable once the application code really builds up.
Should you require any further clarifications and/or code samples, just comment here. I haven't included them as it's trivial and extrapolates the logic and the syntax you're already familiar with.

Dynamic nested routing in angularJs

Trying to implement the following route system with angular stateProvider:
some_domain.com/abc/pqr/xyz
Issue is the number of levels after "some_domain.com" can vary. It can be like
some_domain.com/abc/pqr/xyz
some_domain.com/abc/pqr
some_domain.com/abc
some_domain.com/abc/pqr/xyz/1234
tried the many approaches for this in the state definition:
$stateProvider
.state('dummy', {
url: '/*',
templateUrl: 'views/home.html',
controller: 'LandingPage'
});
}]);
Can anybody help me regarding this?
As the parameters you are talking about are part of the route itself, so you cannot have a single route to handle all these cases. I can think of 2 ways to go about it :
Create a seperate route for each case.
Use optional parameters if you can modify the logic accordingly. If the parameters can be optional, they should sent as query parameters instead of making them part of URL as such. So, the URL becomes something like :
url: '/dummy?param1?param2?param3'

How to structure ui-router to have SEO friendly url structure

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.

Angular ui-router: Mix static with dynamic routes

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}}"

ui-router: Is there a way to have variables in the beginning of the url?

I'd like to have a variable in my route like this:
$stateProvider
.state('edit', {
url: ':organization/edit',
templateUrl: 'partials/edit.html',
controller: 'editController',
controllerAs: 'editController'
})
And have that working at the same time as using
$urlRouterProvider.otherwise('index');
Is that possible? Because what I find is that the otherwise-rule kicks in when I try to go to
myOrganization/edit
and then I'm redirected to index. What am I missing here?
This should be possible, as shown here. The trick is to define index as the first state (well, not as a first, but before the edit):
.state('index',{
url:'/index',
template:'<div>index</div>',
})
.state('edit', {
url: '/:organization/edit',
...
})
The ui-router will evaluate url state by state, as they where defined. The first match will decide. So if the index, in this case is found, index state is selected...
Check it here
My (private) suggestion would be: do not count on order. Try to define states to be really simply identified. Even more, my experience is, that if users do use url, they copy/paste... so, it could be a bit more talkative...

Resources