将URL传递给AngularJS app中的$ routeParam

Raf*_*zak 16 javascript url-routing angularjs

如何将实际URL(带斜杠,逗号等)作为$ routeParam传递给AngularJS App?

这将工作:http: //paprikka.github.io/le-bat/#/preview/asdadasda

这不会:http://paprikka.github.io/le-bat/#/preview/http : //page.com

这也不会:http: //paprikka.github.io/le-bat/#/preview/http%3A%2F%2Fpage.com

或者:http: //paprikka.github.io/le-bat/#/preview/?url = http%3A%2F%2Fpage.com

细节

AngularJS路由机制的设计不允许使用斜杠作为查询参数传递字符串.我能理解这个决定背后的原因 - 我们不想在这里创建一个无状态服务器.

但是,仍然存在在路径中使用不同分隔符或正则表达式的情况.

我想创建一个应用程序,它接受一个url哈希字符串参数并将其内容加载到iframe(此处链接).路由以非常标准的方式设置(我使用的是Coffeescript,但这个片段与纯js没有区别):

$routeProvider
  .when('/preview/:src', {templateUrl: 'partials/preview.html',
  controller: 'PreviewCtrl'})
  .when('/preview', {templateUrl: 'partials/preview.html',
  controller: 'PreviewCtrl'})
Run Code Online (Sandbox Code Playgroud)

当然,我可以在AngularJS被引导之前从哈希加载url,然后将它传递给库,但如果我还可以在更改范围内的数据时更新当前路由参数,这将是很好的 - 这就是为什么我认为最好不要避免AngularJS API.

mat*_*wad 17

在Angular 1.2中使用$ routeProvider,如果它位于路径的末尾,则可以通过向模式添加星号来传入URL.无论你是否URLComponentEncode url,以下应该工作.

路线:

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

控制器:

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

然后在你的模板中:

<iframe ng-src="{{picture_url}}"></iframe>
Run Code Online (Sandbox Code Playgroud)

  • 这对我不起作用.传递URL时路由仍然不匹配. (3认同)

Raf*_*zak 5

好的,我已经设法找到一个使用当前稳定版本(@ 1.0.7)的解决方案.

当前处理此问题的方法将涉及与路由相关的事件,即时解析角度不兼容的URL并通过与$ http拦截类似的方式处理它们来处理它们.

您可以在此处查看工作代码示例:http://embed.plnkr.co/fIA2xj/preview

主要步骤

  1. 像往常一样传递角度不兼容的URL,例如.转到site.com/url/ http://site.com
  2. 监听$ routeChangeStart事件,并为以#开头的路径提取正确的url参数 /url/
  3. 将正确的url参数编码为角度兼容的形式(在这种特殊情况下,我使用base64).不要使用encodeURIComponent,因为angular将视为任何其他url
  4. 使用您的业务逻辑重定向到另一个路由,例如.site.com/parsed-url/BASE64_GOES_HERE
  5. 解码控制器中的URL并像往常一样使用它:)

像往常一样创建角度app模块

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'});

  }

])
Run Code Online (Sandbox Code Playgroud)

URL拦截器服务(单例)

.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
  }
})
Run Code Online (Sandbox Code Playgroud)

控制器

// 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);
});
Run Code Online (Sandbox Code Playgroud)

你应该记住两件事:

  1. 虽然我试图创建一个尽可能干净的解决方案,但通常将数据以这种方式传递给角度并不是一个好习惯,所以尽管不需要使用它,尽量不要使用它.
  2. 您只需一条路线即可处理此问题.我只是觉得这样清洁.