18

I have a 'route' in Angular JS as follows

$routeProvider.when('/foos/:fooId', { controller: FooController, templateUrl: 'foo.html'});

and it works great, unless the :fooId component contains either a '/' or '%2F' (encoded form)

How can I make this work, my 'fooId' can contain /s ?

ConfusedNoob
  • 9,826
  • 14
  • 64
  • 85
  • You currently cannot.. see http://stackoverflow.com/a/12685266/158502 -- you CAN hack it up like this if you like: http://stackoverflow.com/a/16600968/158502 – Langdon May 19 '13 at 02:51
  • but the / is encoded, I'm not creating nested components. Just one component - that might contain a %2F. If that doesn't work, it seems like a bug, no? – ConfusedNoob May 19 '13 at 02:54
  • Right, but it's urlencoded... so when you click on the link that is tied to the url, its going to unencode. I just noticed you can actually double encode it, and end up with %2F in `$route.current.params` that you'll have to decode yourself. Use `%252F`. – Langdon May 19 '13 at 02:56

4 Answers4

13

You can't easily do this because if you use a link with %2F in it, the browser will just decode it for you and it'll end up being /. AngularJS currently doesn't allow you to use / in $route params.

You can double encode it, like in this plnkr: http://plnkr.co/edit/e04UMNQWkLRtoVOfD9b9?p=preview

var app = angular.module('app', []);

app.controller('HomeCtrl', function ($scope, $route) {
});
app.controller('DirCtrl', function ($scope, $route) {
  var p = $route.current.params;

  $scope.path = decodeURIComponent(p.p1);
});

app.config(function ($routeProvider) {
    $routeProvider
            .when('/', {templateUrl: 'home.html', controller: 'HomeCtrl'})
        .when('/dir/:p1', {templateUrl: 'dir.html', controller: 'DirCtrl'})
            .otherwise({redirectTo: '/'});

});

And the link would be: <a href="#/dir/a%252Fb%252Fc">click here</a>.

Another option, if you have a set number of / characters in your parameters can be found here: How can I make the angular.js route the long path

Community
  • 1
  • 1
Langdon
  • 19,875
  • 18
  • 88
  • 107
  • 2
    I had to manually double encode and re-encode: function encodeSlash(uri) { return uri.replace(/\//g, '%252F').replace(/%2F/gi, '%252F'); } function decodeSlash(uri) { return uri.replace(/%2F/gi, "/"); } These are used whenever writing to the $location or reading (e.g. from $routeParams) but it works great, thanks! – ConfusedNoob May 19 '13 at 03:14
5

Based on the answer of Langdon, I created a filter which encodes everything twice, and another one which decodes:

.filter('escape', function() {
        return function(input) {
            return encodeURIComponent(encodeURIComponent(input));
        }; 
})

.filter('unescape', function() {
        return function(input) {
            return decodeURIComponent(input);
        };
    });

I use this in my product links as follows:

<a href="#/p/{{product.id}}/{{product.name | escape}}">

On the product page, I decode the product name:

<h1>{{product.name | unescape}}</h1>
Fortega
  • 19,463
  • 14
  • 75
  • 113
5

You need not to encode anything here. Just add * in your path Param as mentioned below and enable html5Mode

 app.config(function ($routeProvider, $locationProvider) {
 $routeProvider
.when('/home', {templateUrl: 'home.html', controller: 'HomeCtrl'})
.when('/base/:path*', {templateUrl: 'path.html', controller: 'pathCtrl'})
.otherwise({redirectTo: '/home'});
});

 $locationProvider.html5Mode({
  enabled: true,
  requireBase: false
 });
Jhecht
  • 4,407
  • 1
  • 26
  • 44
Ankur Gupta
  • 301
  • 4
  • 12
1

include $locationProvider.hashPrefix(''); in your config.

Himanshu Shekhar
  • 1,196
  • 1
  • 16
  • 35
  • 2
    Why should the OP "include $locationProvider.hashPrefix('');..."? A **good answer** will always have an explanation of what was done and why it was done in such a manner, not only for the OP but for future visitors to SO. – B001ᛦ Jan 25 '17 at 10:33