Avoiding dynamic routes with ui-router - angularjs

I am using express, angular, and ui-router for my webpage. I would like the url for each user's page to be very simple: www.mysite.com/username
This is similar to Twitter's design. My angular state provider for the user pages looks like this:
$stateProvider
.state('userPage', {
url: '/:username',
templateUrl: 'js/user-page/user-page.html',
controller: 'UserPageCtrl'
});
The only issue is now when I try to navigate to any other page whose state is defined with only one URL part (ie. www.mysite.com/login), the app always parses the URL as a user page (but without being able to find a user).
Is there any way to tell angular to try and load the URL as a defined state before treating the url as a dynamic parameter?
I can simply require all other routes to have two parameters (ie. www.mysite.com/login/userlogin), but that doesn't seem very elegant.

You just need to define the login state first. Order is important.
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'somewhere/login.html',
controller: 'LoginPageCtrl'
},
.state('userPage', {
url: '/:username',
templateUrl: 'js/user-page/user-page.html',
controller: 'UserPageCtrl'
},
});
If a user navigates to /login then a matching state will be searched for. It will check your first state, then the second and so on until a matching state is found. In this case, the login state will match so the searching for another matching state will cease.

Related

Angularjs ui router needs to load child state by default similar to home page

I am using angularjs ui router and I need to load the child state by default (i.e., 'dashboardParent.dashboard').
$stateProvider.state('dashboardParent', {
abstract: true,
url: '/dashboard',
templateUrl: 'app/views/dashboard/dashboard-parent.html',
controller: 'DashboardParentController'
}).state('dashboardParent.dashboard', {
url: '/',
templateUrl: 'app/views/dashboard/dashboard.html',
controller: 'DashboardController'
})
Generally what we do is we have home state with url ("/") from there we navigate to some other state let say 'dashboardParent.dashboard'. But here I don't have any home state. When I start the application I want dashboardParent.dashboard state to be loaded. How to achieve it.
If I add another state home and provide a link to navigate to the state 'dashboardParent.dashboard' it is loading fine. But my requirement is I do not have any home state, instead I need to load 'dashboardParent.dashboard' by default. How to achieve it?
code below will help you:
// if the path doesn't match any of the urls you configured
// otherwise will take care of routing the user to the specified url
$urlRouterProvider.otherwise('/');
reference: URL-Routing of ui-router
note: Don't forget injecting the $urlRouterProvider service.

AngularJS UI Router query parameters search not working as expected

I have a very simple search app using UI Router with 2 states, 2 templates and 1 controller. I have home(enter search query) and search(display results, search more) - states and templates - and am attempting to get the query parameters in the url from home state to search state WITH search results displaying on the first query submission.
What is currently happening is you enter the search query on the home state and you go to the search state and the query parameters appear in the BUT it takes a second search submission for the results to display.
I believe I'm using $stateParams correctly it seems, however I think I'm either missing something or don't have my states setup correctly for this scenario to work as intended.
Do I need to use $location and if so, how? Should I have home as a parent state and then have search as a child state of home and use abstract:true ? Should I not use html5Mode? Trying to get my head around UI Router, not so easy... It seems like this should be easier than what I'm making it to be?
Here are my states
$locationProvider.html5Mode(true);
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'home/home.html',
controller: 'SearchCtrl'})
.state('search', {
templateUrl: 'search/search.html',
url: '/search?q',
controller: 'SearchCtrl'
});
$urlRouterProvider.otherwise('/home');
This is how I'm using $stateParams in SearchCtrl
$scope.searchTerms = $stateParams.q;
searchTerms is my ng-model on the search form
And this is how I'm using $state.go() in my search function in SearchCtrl
$state.go('search', {q: $scope.searchTerms});

Angular UI router dynamically inject URL to html

I am trying to build a simple app, which goes the following way:
I have 2 menu items in the navbar: home and contact.
The home should be a unique URL only once from the server, at initialisation, read from a QR code (i got this covered, that is no problem to me) and the contact should always be the same.
I got the contact done in the following way:
$stateProvider.state('contact', {
url: '/contact',
templateUrl: 'src/views/contact.html',
controller: 'contactController'
})
The problem is with the home, which should keep the unique URL received by the server. How should i write the state for that one?
.state('home', {
url: '/:uid',
templateUrl: 'src/views/home.html',
})
Also, the home should keep it's unique url generated by the server after refresh and while navigating from contact to home.
In the HTML i would have something like
<a ui-sref="home({uid: --some dynamic uid?--})">Home</a>
this is the part which also requires help.
Set the home state to
.state('home', {
url: /{uid},
templateUrl: 'src/views/home.html',
})
and you could grab the parameters by injecting $stateParams into the controller. $stateParams.uid would return the parameters and store that in local storage or cookies.
Check this link out
https://github.com/angular-ui/ui-router/wiki/URL-Routing#stateparams-service
UPDATE:
for example, this is the sample controller that is attached to the home page
app.controller('homeCtrl', function($stateParams) {
var id = $stateParams.uid; //this is how you retrieve the uid
});
by going to your home page e.g. http://www.example.com/abcd12345, the above $stateParams.uid would return abcd12345
Now to set the url. simply use ui-sref instead of href on the <a> tag. ui-router will automatically generate href for you.
e.g.
<a ui-sref="home({uid:'abcd12345'})">Home</a>
You have to create a custom provider and inject it into the config.
eg:- .config($stateProvider, $urlRouterProvider,yourprovider) .
I am not sure about this. But please check this way too..

How to switch to a ui-router state conditionally?

I am writing a CRUD app with AngularJS + UI Router.
I want to be able to parse the current location in the browser URL and determine if a ui-router state should be applicable for the current url.
In these sample routes, is there some way to do the if and unless clauses?
(url in browser address bar is http://example.com/notes/1/edit_me)
$stateProvider.state("root", {
url: "",
unless: $location.matches(/\edit_me/)
})
$stateProvider.state("edit", {
url: "/edit",
if: $location.matches(/\edit_me/)
//
})
UPDATE 1
The reason I want to do the above:
Say I am at http://example.com/notes. The routes is
$stateProvider.state("root", {
url: "",
})
However, with the same above ui.route state, when I am at url http://example.com/notes/edit, the root is now "/notes/edit" instead of "/notes"
UPDATE 2
#adam, more explanation of what I am trying to accomplish:
I will try to explain: in your code, for your home state, the (ui.router's) url is / (aka hash syntax #!/)
However, the URL in browser address bar looks like http://example.com/notes/ in one case and http://example.com/notes/edit in another case. (note that the URLs do not contain any #! portion since we have just navigated to the page)
Now the home's / is going to match in both cases of above URL.
But since the second URL ends in notes/edit, I want that the home for this URL should be #!/edit, and not #!/.
Basically I am trying to mix server-side rendered pages (/notes and /notes/edit are rendered by server, not AngularJS)
and client side routing so that no matter which URL we are at, the client can figure out which (ui.router) route applies to the current URL.
Make sense?
Sorry i don't really understand your needs but here's an example of use of ui-router:
$stateProvider
.state('home', {
url: '/',
templateUrl: 'app/main/index.html',
controller: 'MainCtrl'
})
$stateProvider
.state('edit', {
url: '/edit',
templateUrl: 'app/edit/edit.html',
controller: 'EditCtrl'
})
$stateProvider
.state('edit.note', {
url: '/note',
templateUrl: 'app/edit/note.html',
controller: 'NoteCtrl'
});
$urlRouterProvider.otherwise('/');
i'm not sure if a copy paste will work, but try to adapt it with your case. Hope it will help.
Edit:
I'm afraid that i can't help you more than that. The design of your app with rendered page without angular sounds really special.
Have you tried the example i provide you? If yes, hav you simply format the url by addind
" #!/ " where you need it.
For example:
$stateProvider
.state('edit', {
url: '#!/edit', //or something like, url:'/#!/edit'
templateUrl: 'app/edit/edit.html',
controller: 'EditCtrl'
});
Check this link also may be it will help you:https://github.com/angular-ui/ui-router/issues/372
ui-sref may help you
But the place to see usefull example for ui-router it's his own doc.
https://github.com/angular-ui/ui-router
and here:
http://angular-ui.github.io/ui-router/site/#/api/ui.router

Am I using states correctly?

I have an angular app with a homepage that shows a list of things. Each thing has a type. In the nav, there are selectors corresponding to each thing type. Clicking one of these selectors causes the home controller to filter the things shown to those of the selected type. As such, I see the selectors as corresponding to states of the home page.
Now, I'd like to map each of these states to a url route: myapp.com/home loads the home page in default (unfilitered) state, myapp.com/home/foo opens the home page with the foo-type selector activated, and switching from there to myapp.com/home/bar switches to the bar-filtered state without reloading the page.
It's that last bit - triggering "state" changes without reloading the page, that's been particularly tricky to figure out. There are numerous SO/forum questions on this topic but none have quite hit the spot, so I'm wondering if I'm thinking about this in the wrong way: Should I be thinking of these "states" as states at all? Is there a simpler approach?
Also, I'm open to using either ngRoute or ui.router - is there anything about one or the other that might make it simpler to implement this?
Using ui-router, you can approach it like this:
$stateProvider
.state('home', {
url: "/home",
controller: "HomeController",
templateUrl: "home.html"
// .. other options if required
})
.state('home.filtered', {
url: "/{filter}",
controller: "HomeController",
templateUrl: "home.html"
// .. other options if required
})
This creates a filtered state as a child of the home state and means that you can think of the URL to the filtered state as /home/{filter}. Where filter is a state parameter that can then be accessed using $stateParams.
Since you don't want to switch views, you inject $stateParams into your controller, watch $stateParams.filter, and react to it how you wish.
$scope.$watch(function () { return $stateParams.filter }, function (newVal, oldVal) {
// handle it
});

Resources