将URL传递给AngularJS app中的$ routeParam

时间:2013-04-27 20:33:06

标签: javascript angularjs url-routing

如何将实际的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(link here)的应用。路径以非常标准的方式设置(我使用Coffeescript,但这个片段与纯js没有区别):

$routeProvider
  .when('/preview/:src', {templateUrl: 'partials/preview.html',
  controller: 'PreviewCtrl'})
  .when('/preview', {templateUrl: 'partials/preview.html',
  controller: 'PreviewCtrl'})

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

4 个答案:

答案 0 :(得分:17)

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

路线:

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

控制器:

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

然后在你的模板中:

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

答案 1 :(得分:5)

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

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

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

主要步骤

  1. 像往常一样传递角度不兼容的网址,例如。转到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并照常使用它:)
  6. 代码

    照常创建角度应用模块

    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拦截器服务(单件)

    .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
      }
    })
    

    控制器

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

    你应该记住两件事:

    1. 虽然我试图尽可能地创建一个干净的解决方案,但通常将数据以这种方式传递给angular也不是一个好习惯,所以除非你真的需要,否则不要使用它。
    2. 您只需一条路线即可解决此问题。我只是觉得它更清洁。

答案 2 :(得分:1)

我有一个解决方案,但我不知道它是否会对你有帮助。来自Angular documention http://docs.angularjs.org/api/ng。$ location $ location有一个函数搜索(search,paramValue)

传递参数:

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

阅读参数:

url = decodeURIComponent $location.search().yourURLParameter

当然你需要注入$ location依赖

答案 3 :(得分:0)

我将搜索参数与路线混合在一起。您的搜索需要在您的路线之前...专门针对旧浏览器。我认为ie7如果不是url/?search/#/hash

就会爆炸

请尝试以下格式:

domain.com/?my=params&another=param/#/my/hashes
相关问题