I set UI Router up to have query parameters in the url, but when I did that it broke the search functionality on my app.
My states are like this:
.state('home', {
url: '/home',
templateUrl: 'home/home.html',
controller: 'HomeCtrl'})
.state('search', {
url: '/search?q',
templateUrl: 'search/search.html',
controller: 'SearchCtrl'
});
I have this code in both HomeCtrl and SearchCtrl:
$scope.searchTerms = $stateParams.searchTerms;
The HomeCtrl basically serves as an autocomplete/query page.
Then I have this:
$state.go('search', {q: $scope.searchTerms});
in my getSuggestions function on HomeCtrl and search function in SearchCtrl
In order for this to work, I have to search twice...? I enter the query and hit enter and the query appears in the url, then I have to hit enter again for the results to display. It doesn't work at all if I click the search button :(
If I comment out the $state.go line, search works but I loose the query parameters in the url and vice versa. It seems like $scope is getting turned off somehow?
Should I use ui-sref (it is more common) instead of $state.go for the linking? Am I suppose to put the $state.go code on the button element or something?
What am I doing wrong... so that search works and I have query parameters in the url?
Related
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});
I have an odd issue where I use an ng-click to $state.go() to a state, and get the correct url but the wrong template and controller.
These are my states:
app.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise("/messages");
$stateProvider.state('message', {
url: "/messages/:to/:fro/:messageID",
templateUrl: 'message.html',
controller: 'MessageCtrl'
}).state('compose', {
url: "/messages/compose/a/message",
templateUrl: 'compose.html',
controller: 'ComposeCtrl'
});
});
This is the function triggered by my ng-click and I am in fact getting the console log so I know the right one is firing.
$scope.composeMe = function(){
console.log("You want to compose a message!");
$state.go("compose");
};
When I fire that function I get the url to change to http://example.com/messages/compose/a/message but I get the templateUrl and the controller of the message state.
Why is that? The other state is fired from a similar (ng-click derived) function and works perfectly.
The URL you are trying to go to matches the one you are actually going to.
How would ui-router know that "compose" isn't the to: field you want, "a" isn't the fro: field you want, and "message" isn't the messageID you want?
Move the more specific state definition above the one with URL parameters.
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.
I have this simple state :
.state('search', {
url: '/search',
templateUrl: 'views/search.html',
controller: 'search'
})
And I would like to pass any extra unplanned parameters to the controller when using search state or /search route :
ui-sref="search({foo:1, bar:2})"
// would call '#/search?foo=1&bar2',
// match the state and pass foo and bar to the controller (through $stateParams)
When I try this, it matches the otherwise of the router instead. :(
I've read a lot of solutions that imply to declare each parameter in the state:
.state('search', {
url: '/search?param1¶m2¶m3?...',
})
But I cannot do this as far as the parameters list is not really defined and changes all the time depending on searched content.
Is there a way to achieve this ? Or am I wrong somewhere ?
Thx.
EDIT : When I try to call directly this url : #/search?foo=1, the state search matches but the foo parameter never goes to $stateParams which is empty. I don't know how to get it in.
.state('search', {
params: ['param1','param2','param3'],
templateUrl: '...',
controller: '...'
});
ui-sref="search({param1:1, param2:2})"
Credit goes to Parameters for states without URLs in ui-router for AngularJS
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