Dynamic route params in AngularJS - 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).

Related

Dynamic parameters with ui-router

I'm developing a search app with angular using ui-router.
Requirements:
The search form has too many fields and all have to be optional.
Users should share with another users the URL that display the page with the result list. (So I need to use querystring)
So I could have urls like
path/to/url/list?p=123&v=876
path/to/url/list?c=yes&a=true&p=123
path/to/url/list?z=yes&c=yes&a=true&p=123
path/to/url/list?z=yes&v=876&a=true&p=123
And endless combinations. I know that I can use $location.search() to get all params in json format. That is great! but the question is How can I define the url state with ui-router? Define explicitly all params in the url is not an option. I have read many post but I didn't find a concrete answers.
If you're getting parameters from $location you don't need to define them in state explicitly.
I think, the best way is to use 'resolve' property of $stateProvider configuration:
$stateProvider.state('mystate', {
// Some code here
resolve: {
queryData: ['$location', ($location) => {
$location.absUrl(); // Contains your full URI
return true;
}]
}
});
It's kind of initialization. After that, ui-router will cut URI, but you will store needed data. This case also works fine, when user passing URI directly in browser address input.
Also you can try to set $urlRouterProvider with $urlMatcher for this purposes, but it will be more difficult.

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.

How to create AngularJS Route with dashes instead of slashes

Is it possible to create Angular routes with dashes instead of slashes, and variable content in the URL fragment? For example:
In the Angular phone Tutorial, URLs look like this, e.g:
http://angular.github.io/angular-phonecat/step-11/app/#/phones/motorola-xoom
this is implemented via a Route Provider such as:
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
})
what I'd like to do is have URLS that look more like:
http://angular.github.io/angular-phonecat/step-11/app/#/phones/{{manufacturer}}--{{devicename}}--{{phoneid}}
where {{phoneid}} is a numerical database key and the {{manufacturer}} text will vary from phone to phone. This is because I need the numerical key to drive my database but want the manufacturer & devicename text (or my equivalent) in the URL for seo purposes....
Effectively I'd like to do in Angular Routes what I can do in htaccess files, where I'd do something like:
RewriteRule ^(.)--by--(.)--(.*)$ phone.php?mfg=$1&devicename=$2&phoneid=$3
I know Angular routes don't support wildcards like this, but wondering how I might be able achieve an effect somewhat like this. Or maybe there is some extension which enables this?
You can use variable using :name in the url (source)
In your config:
config(function($routeProvider, $locationProvider) {
$routeProvider
.when('/phones/:manufacturer--:devicename--:phoneid', {
templateUrl: 'file.html',
controller: 'PhoneController'
});
To access the parameters in your controller:
$routeParams.manufacturer
$routeParams.devicename
$routeParams.phoneid

Problems with AngularJS $location.path

I am having fun and games with a troublesome AngularJS route, so lets see if I can explain this as well as I can.
APP.JS:
app = angular.module("index", []);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/booking/damage/:regnumber', {
templateUrl: 'damage',
controller: 'DamageCtrl'
}).
otherwise({
redirectTo: '/'
});
}
]);
app.controller('IndexCtrl', function($scope, $location) {
$scope.regnumber = '';
$scope.progress = function() {
if ($scope.regnumber !== '') {
$location.path('/booking#/damage/' + $scope.regnumber);
} else {
$location.path('/booking#/damage');
}
};
});
My initial page has a path of
http://localhost/windscreens/glass/index#/index
and within this page is a form that via ng-submit="progress() calls the $scope.progress function within my IndexCtrl controller. There is a field in the form of ng-model="regnumber".
So when filling in the input field with lets say "ABC" and clicking on the button, I'd expect the path to become:
http://localhost/windscreens/glass/booking#/damage/ABC
But it becomes
http://localhost/windscreens/glass/index#/booking%23/damage/ABC
Thing is I am still really becoming used to the Angular routing system and haven't quite got it yet. Any advice on this will be appreciated!
Why am I seeing what I am seeing? What have I got wrong here?
The Angular $routeProvider can only change the part of the URL after the hash (#), so when calling $location.path(), you just use a plain URL fragment like you defined in the route for DamageCtrl.
Some explanation
I'm going to simplify a bit here, but hopefully it will help you understand what's going on.
You're making a SPA (single-page app), so the URL you enter in your browser to get into your app doesn't change while you navigate between routes; by default $routingProvider appends #/whatever/route to that base URL. In your case it looks like you have your entry point (ng-app) in a file called /windscreens/glass/index, so all routes will get appended to that.
Because you don't have an /index route defined that we can see, I'm not sure how http://localhost/windscreens/glass/index#/index is working for you. It should send you to http://localhost/windscreens/glass/index#/ because your otherwise route is just /.
Back to the question
If I understand your question correctly, I would make the index file (where ng-app lives) /windscreens/glass/index.html, then you can just enter http://localhost/windscreens/glass/ to get into the app, because the webserver will serve the contents of index.html by default.
At that point, your index page URL would become http://localhost/windscreens/glass/#/, and your /booking/damage/ routes would be http://localhost/windscreens/glass/#/booking/damage/ABC etc. The code to navigate to them would then be
$location.path('/booking/damage');
Angular routing changes the route on the page; it doesn't take you to a new directory or page.
So if index.html contains your Angular app and you have routes for "booking", "reservation", "cancellations", etc. You'll end up with urls that look like:
/glass/index.html#/booking
/glass/index.html#/reservation
/glass/index.html#/cancellations
The route merely appends itself to the index.html.
So, in a sense, your routes are working correctly. The %23 that you see being added is the url encoded # sign.
If you have a second Angular app that is found at /glass/booking and you're trying to forward the user to it, you can use $window.location.hash and $window.location.pathname. For example,
$window.location.hash = "/damage/ABC";
$window.location.pathname = "/windscreens/glass/booking";
should take you to:
/windscreens/glass/booking#/damage/ABC

how to pass querystring in angular routes?

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}

Resources