Skip to content Skip to sidebar Skip to footer

Pass URL To As $routeParam In AngularJS App

How can I pass actual URL (with slashes, commas, etc.) as a $routeParam to AngularJS App? this will work: http://paprikka.github.io/le-bat/#/preview/asdadasda this won't: http://pa

Solution 1:

Using $routeProvider in Angular 1.2, you can pass in a url if it's at the end of the path by adding an asterik to the pattern. The following should work whether or not you URLComponentEncode the url.

The route:

angular.module('angularApp', ['ngRoute'])
      .when('/frame/:picture_url*', {
        templateUrl: 'views/frame.html',
        controller: 'PictureFrame'
      });

The controller:

      .controller('PictureFrame', function($scope, $routeParams, $sce){
        //whitelist the URL
        $scope.picture_url = $sce.trustAsResourceUrl($routeParams.picture_url);
      });

Then in your template:

<iframe ng-src="{{picture_url}}"></iframe>

Solution 2:

Ok, I've managed to find a solution working with current stable version (@1.0.7).

Current way of handling this problem will involve $route-related events, parsing angular-incompatible urls on the fly and handling them via an additional service working in a similar way as $http interception.

You can see working code examples here: http://embed.plnkr.co/fIA2xj/preview

Main steps

  1. pass an angular-incompatible url as usual, eg. go to site.com/url/http://site.com
  2. listen to a $routeChangeStart event and extract correct url parameter for paths beginning with /url/
  3. encode the correct url parameter to an angular-compatible form (in this particular case, I use base64). Don't use encodeURIComponent, because angular will treat as any other url
  4. redirect to another route with your business logic, eg. site.com/parsed-url/BASE64_GOES_HERE
  5. decode the URL in the controller and use it as usual :)

Code

Create angular app module as usual

angular.module('routes',[]).config([

  '$routeProvider',

  function($routeProvider){
    $routeProvider
      .when('/test', {templateUrl: 'test.html'})
      // This one is important:
      // We define a route that will be used internally and handle 
      // parameters with urls parsed by us via the URLInterceptor service 
      .when('/parsed-url/:url', {templateUrl: 'url.html', controller:'URLCtrl'})
      .when('/', {redirectTo: '/test'})
      .otherwise({templateUrl: '404.html'});

  }

])

URL Interceptor service (singleton)

.service('URLInterceptor', function($rootScope, $location){
  // We listen to $routeChangeStart event and intercept it if 
  // the path matches our url scheme. In this case, every route
  // beginning with /url/ will be caught
  $rootScope.$on('$routeChangeStart', function(e, next, current){

    // $location.path does change BEFORE actual routing happens,
    // so in this case we get parsed new location object
    // for free.

    // To be hones, a better way of handling this case might be using 
    // $locationChangeStart event instead, but it would require us to parse urls 
    // manually.
    var path = $location.path();
    // check if string begins with '/url/'
    var matcher = path.slice(0,5);
    var cleanPath = '';
    if (matcher === '/url/'){
      // Yes it does, yay!
      // Remove leading '/url/' to extract the actual parameter
      cleanPath = path.slice(5);
      // Encode our url to a safe version. We know that encodeURIComponent won't 
      // work either, so a good choice might be base64.
      // I'm using https://code.google.com/p/javascriptbase64/downloads
      $location.path('/parsed-url/' + Base64.encode(cleanPath));
      // Prevent default event execution. Note that, it won't cancel related $location Events
      e.preventDefault();
    }
  });

  return {
    decode: Base64.decode,
    encode: Base64.encode
  }
})

Controllers

// Main application controller
// We instantiate our URLInterceptor service here
.controller('AppCtrl',function($scope, $location, URLInterceptor){
  $scope.navigateTo = function (path) {
    $location.path('/url/' + path);
  }
})
.controller('URLCtrl', function($scope, $routeParams, URLInterceptor){
  $scope.url = URLInterceptor.decode($routeParams.url);
});

Two things you should remember:

  1. Although I tried to create a solution as clean as possible, usually passing the data this way to angular isn't considered a good practice, so try not to use it unless you really need to.
  2. You can handle this issue with only one route. I just find it cleaner this way.

Solution 3:

I have a solution but I don't know if it will help you. From Angular documention http://docs.angularjs.org/api/ng.$location $location has a function search(search, paramValue)

To pass the parameter:

parameter = encodeURIComponent url
$location.search({ yourURLParameter: parameter }).path('/preview')

To read the parameter:

url = decodeURIComponent $location.search().yourURLParameter

Of course you need to inject $location dependency


Solution 4:

I have mixed search params with routes. Your search needs to come before your routes.. specifically for older browsers. I think ie7 blows up if its not url/?search/#/hash

Try this format:

domain.com/?my=params&another=param/#/my/hashes

Post a Comment for "Pass URL To As $routeParam In AngularJS App"