how to pass querystring in angular routes? - angularjs

I am working with AngularJS routes, and am trying to see how to work with query strings (for example, url.com?key=value). Angular doesn't understand the route which contains key-value pair for the same name albums:
angular.module('myApp', ['myApp.directives', 'myApp.services']).config(
['$routeProvider', function($routeProvider) {
$routeProvider.
when('/albums', {templateUrl: 'albums.html', controller: albumsCtrl}).
when('/albums?:album_id', {templateUrl: 'album_images.html', controller: albumsCtrl}).
otherwise({redirectTo: '/home'});
}],
['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode = true;
}]
);

It is correct that routes do not work with query strings, however that doesn't mean you can't use query strings to pass data between pages when switching routes! The glaring limitation with route parameters is that they can't be updated without reloading the page. Sometimes this isn't desired, for instance after saving a new record. The original route parameter was a 0 (to signify a new record), and now you want to update it with the correct ID returned through ajax so that if the user refreshes the page they see their newly saved record. There is no way to do this with route parameters, but this can be accomplished by using query strings instead.
The secret is not to include the query string when changing the route, because that will cause it not to match the route template. What you can do is change the route and then apply the query string parameters. Basically
$location.path('/RouteTemplateName').search('queryStringKey', value).search( ...
The beauty here is that the $routeParams service treats query string values identically to real route parameters, so you won't even have to update your code to handle them differently. Now you can update the parameters without reloading the page by including reloadOnSearch: false in your route definition.

I don't think routes work with query strings. Instead of url.com?key=value can you use a more RESTful URL like url.com/key/value? Then you would define your routes as follows:
.when('/albums', ...)
.when('/albums/id/:album_id', ...)
or maybe
.when('/albums', ...)
.when('/albums/:album_id', ...)

You could look at the search method in $location (docs). It allows you to add some keys/values to the URL.
For example, $location.search({"a":"b"}); will return this URL: http://www.example.com/base/path?a=b.

use route params
var Ctrl = function($scope, $params) {
if($params.filtered) {
//make sure that the ID is there and use a different URL for the JSON data
}
else {
//use the URL for JSON data that fetches all the data
}
};
Ctrl.$inject = ['$scope', '$routeParams'];
http://docs.angularjs.org/api/ng.$routeParams

I can only think of two usecases for the querystring in URL:
1) If you need the key/value pair of your querystring in your controller (eg. to print Hello {{name}} and get the name in querystring such as ?name=John), then as Francios said just use $location.search and you will get the querystring as an object ({name:John}) which you can then use by putting it in scope or something (e.g. $scope.name = location.search().name;).
If you need to redirect to another page in your router based on what is given in the querystring, like (?page=Thatpage.htm) then create a redirectTo: in your routerProvider.when() and it will receive the search object as its third parameter. look at 2:10 of the following EggHead Video:
http://www.thinkster.io/pick/SzcF8bGeVy/angularjs-redirectto
basically, redirectTo:function(routeParams,path, search){return search.page}

Related

How do I parse the location path in AngularJS?

For example the page is 'http://mywebsite/details/555', how can I get that '555' out of there in my controller? It's not a parameter, so I cannot look up for it by name.
Have a look at the Angular routing parameters. The number you want is actually and id used in the routing path which you can catch:
https://angular.io/guide/router
https://angular-2-training-book.rangle.io/handout/routing/routeparams.html
Your are writing that 555 is not a parameter - but I think you want to use it like a parameter. Parameters look like: http://mywebsite/#/details/555
You can then define this in your router (here I'm using ui-router, but you can do the same with ng-route:
$stateProvider
.state('details.id', {
url: "/details/:id",
templateUrl: 'detail.html',
controller: myController
})
See https://github.com/angular-ui/ui-router/wiki/URL-Routing
If you still want to parse your URL string, you can do it this way:
var detailId = this.href.substr(this.href.lastIndexOf('/') + 1);
But the right (and probably the only working) way is to use the router for that.

Create Angular Dynamic Route

I have a route string like the following var global_book_route = /books/:id specified in a variable.
I want to be able to use $route or $location to deep link to this route in a controller, is there a way to do this without re-specifying the url prefix?
This would work: var id=1; $location.path('books/'+id') -> '/books/1'
However, this does not: $location.path(global_book_route).search({id:1}) -> 'books/:id?id=1'
Is there a way I can use the route specified in the string to go to the correct location?
I think you are mixing up the route itself (/books/:id) with the representation of the route in your code.
For example, your global_book_route should be only "/books/".
Then, if you want to load a specific book, you can go the the location global_book_route + book_id as long as the route is declared in your code, like:
$routeProvider
.when('/Book/:bookId', {
templateUrl: 'book.html',
controller: 'BookController',
resolve: {
}
})
On a side node, when dealing with routes in Angular, it's really worth it to look into angular-ui, the ui-router offers a way better system to manage your routes and states.

Force ui-router to reload on querystring changes

I have a state defined something like this:
$stateProvider.state("app.search", {
url: "/search?q",
templateUrl: "App/Search.html",
controller: "SearchController as vm",
});
When I want to navigate to the search page and specify a search term, I can do something like this:
$location.path("search").search({ q: "stuff" });
Which effective resolves to a url along the lines of #/search?q=stuff. If I then change the search term to "things", the search page correctly reactivates and searches as expected.
However, I'd like to be able to specify "random" querystring parameters which have not been defined in my url, and then have those parameters also reload the state. (Note: this is why I'm using $location.path instead of $state.go to change the URL). So for example, if I was searching for food, my URL may be:
#/search?q=stuff&type=food
And then I may be filtering on spice levels, which may change the URL to:
#/search?q=stuff&type=food&spice=medium
(etc).
The problem though, is that since I haven't defined all the other query string parameters (type and spice in this example), ui-router doesn't reload my page.
I can't use $state.go with { reload: true } because it ignores the unspecified parameters.
Is there a way I can trigger a page reload using "unspecified" querystring parameters? This post suggests I can make the route /search* but that doesn't appear to work for me.
I haven't found a nice way to do this yet with ui-router. If you're willing to sacrifice your integrity a little bit you could utilize an alternate format for your query params. You can use a single http url query param object and list all your criteria using a custom format.
e.g.
/search/q?stuff:type=food:spice=cinnamon
The route setup would look like:
$stateProvider.state("app.search", {
url: "/search?q",
templateUrl: "App/Search.html",
controller: "SearchController as vm",
});
and to navigate with the extra parameters:
$state.go('app.dashboard', { q: 'stuff:type=dessert:spice=cinnamon'});
to access the parameters on the route:
$state.params.q
You can then just parse out the 'stuff' value and then each name/value pair that was passed in.
PS> I'm not sure whether the colon (:) separator is valid but it was used to illustrate the proposed idea.

Angularjs multiple urls for same state

Making a verify account page and want to be able to pass an email and auth code via url like so:
https://mywebsite.com/verify?email=a#a.com&code=1234
It looks like I can't do it this way in angular. And should instead be done like this:
https://mywebsite.com/verify/:email/:code
And use $stateParams to grab the vars.
Can you have two different URLs trigger the same state? So both URLs below trigger the same state and the controller checks for the vars and does it's magic.
https://mywebsite.com/verify
https://mywebsite.com/verify/:email/:code
You can set the configuration as like below and you can pass the param which is required to send for the url
$stateProvider.state('verify', {
url: '/verify?email&code',
templateUrl: 'verify.html',
controller: 'verifyCtrl'
});
working fiddle: http://plnkr.co/edit/AwHkFj?p=preview
Rather than defining the params email and code as path parameters, you could use search parameters and access them via $routeParams.
e.g, your route would be:
$routeProvider.when('/verify', routeConfig);
the URL would be:
https://mywebsite.com/verify?email=a#a.com&code=1234
And in the controller, you would inject $routeParams and access via:
$routeParams[email]; // = a#a.com
$routeParams[code]; // = 1234
For more info on $routeParams, see https://docs.angularjs.org/api/ngRoute/service/$routeParams

Dynamic route params in AngularJS

I am familiar with angularjs
When I want to add my routing to my application I use $routeProvider
In $routeProvider.when(), I define routes.
How to define a route If I have a directory browser like structure like:
http://myfolderbrowserapp.com/:folder1/:folder2/.../:folderN
Is it possible with angularjs like:
$routeProvider.when('/**', {
template:'template'
})
Is this possible with angular routing? If not is there a workaround?
Please help
From $routeProvider docs
path can contain named groups starting with a colon and ending with a
star: e.g.:name*. All characters are eagerly stored in $routeParams
under the given name when the route matches.
So you could define
$routeProvider.when('/:folders*', {
template:'template'
})
And then (in controller e.g.)
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
if (angular.isDefined($routeParams.folders))
var foldersArray = $routeParams.folders.split('/');
});
However the path definition /:folders* is too generic and would probably be matched even in cases when you do not want to (don't know how your other paths look like).

Resources