34

I have a block in my angular JS template a la

<a href="#/foos/{{foo.id}}">{{foo.name}}</a>

However, the foo.id property can sometimes contain funky characters ('/'). I want to do something like this:

<a href="#/foos/{{encodeURIComponent(foo.id)}}">{{foo.name}}</a>

but it doens't work? How can I fix this?

ConfusedNoob
  • 9,826
  • 14
  • 64
  • 85
  • I saw this answer - http://stackoverflow.com/a/14512986/775359 - and I was wondering - why I cannot use ```encodeURIComponent``` directly in the template... Apparently a filter is required. – Mars Robertson Aug 09 '16 at 08:50

3 Answers3

70

You could create a filter that calls encodeURIComponent

E.g.

var app = angular.module('app', []);
app.filter('encodeURIComponent', function() {
    return window.encodeURIComponent;
});

Then do

<a href="#/foos/{{foo.id | encodeURIComponent}}">{{foo.name}}</a>

Running example: http://jsfiddle.net/YApdK/

jimr
  • 11,080
  • 1
  • 33
  • 32
  • 4
    This feels wrong just to use one function but it worked immediately. – Michael J. Calkins Jul 20 '13 at 03:36
  • Thanks, very impressive example providing javascript to html with a very short syntax – blacelle Aug 22 '14 at 22:18
  • 3
    As @RickJolly pointed out, you should use `ng-href`instead of `href` to be sure that links are rendered by angular before they can be clicked. You should also probably inject `$window` into the filter instead of using `window` directly. – AJ Richardson Sep 29 '15 at 16:22
  • 1
    jimr beat me, but it's also worth noting that you should use ng-href instead of href to be sure that links are rendered by angular before they can be clicked. – Rick Jolly May 19 '13 at 01:48
14

Reworked @jimr's code, taking into account @aj-richardson's recommendations.

You can use filters within expressions to format data before rendering it.

Create a filter:

var app = angular.module('app', []);
app.filter('encodeURIComponent', function($window) {
    return $window.encodeURIComponent;
});

Then apply the filter:

<a ng-href="#/foos/{{foo.id | encodeURIComponent}}">{{foo.name}}</a>
  • ng-href is used instead of href to be sure that links are rendered by AngularJS before they can be clicked.
  • $window is injected into the filter instead of using window directly.

    You should refer to global window through the $window service, so it may be overridden, removed or mocked for testing.


References:

  1. AngularJS API: $window
  2. AngularJS Developer Guide: filters
  3. AngularJS Developer Guide: expressions
Community
  • 1
  • 1
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
0

If you want to handle malformed URI error, then you have to write a filter function and then use try-catch around the encodeURIComponent.

var app = angular.module('app', []);
app.filter('encodeURIComponent', function($window) {
    return function (path) {
        try {
            return $window.encodeURIComponent(path);
        } catch(e) {
            return path;
        }
    }
});
Fizer Khan
  • 88,237
  • 28
  • 143
  • 153