通过网址为$ routeParam在AngularJS应用 [英] Pass URL to as $routeParam in AngularJS app

查看:172
本文介绍了通过网址为$ routeParam在AngularJS应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何通过实际的URL(用斜杠,逗号等)为$ routeParam到AngularJS应用程序?

这将工作:
<一href=\"http://paprikka.github.io/le-bat/#/$p$pview/asdadasda\">http://paprikka.github.io/le-bat/#/$p$pview/asdadasda

这不会:
<一href=\"http://paprikka.github.io/le-bat/#/$p$pview/http://page.com\">http://paprikka.github.io/le-bat/#/$p$pview/http://page.com

都不会对这样的:
<一href=\"http://paprikka.github.io/le-bat/#/$p$pview/http%3A%2F%2Fpage.com\">http://paprikka.github.io/le-bat/#/$p$pview/http%3A%2F%2Fpage.com

或该:
<一href=\"http://paprikka.github.io/le-bat/#/$p$pview/?url=http%3A%2F%2Fpage.com\">http://paprikka.github.io/le-bat/#/$p$pview/?url=http%3A%2F%2Fpage.com

详细信息

AngularJS路由通过它的设计机制不允许通过字符串与斜线的查询参数。我能理解这个决定背后的原因 - 我们不希望在这里创造一个无状态的服务器。

不过,使用不同的分隔符,或者在定期航线前pressions时可能需要仍然是个案。

我想创建一个应用程序,需要一个URL的哈希字符串参数并加载其内容的iframe(这里链接>)。路由设置在pretty标准的方式(我用的CoffeeScript,但这个片段并不纯JS不同):

  $ routeProvider
  。当('/ preVIEW /:SRC',{templateUrl:'谐音/ preview.html',
  控制器:'previewCtrl'})
  。当('/ preVIEW',{templateUrl:'谐音/ preview.html',
  控制器:'previewCtrl'})

当然,我可以从哈希AngularJS被自举前加载URL,然后把它传递给库,但它会很好,如果我还可以在范围上不断变化的数据时更新当前路由参数 - 这就是为什么我认为这是更好不避AngularJS API。


解决方案

好吧,我设法找到与当前的稳定版本的工作(@ 1.0.7)的解决方案。

的处理这个问题将涉及$路线相关的事件,在飞行解析角不相容网址,并通过一个附加的服务以类似的方式工作作为$ HTTP拦截

处理它们电流方式 HTTP:

您可以在这里看到工作code例子//embed.plnkr。 CO / fIA2xj / preVIEW

主要步骤


  1. 传递一个角不兼容的网址像往常一样,例如。去site.com/url/ http://site.com

  2. 听$ routeChangeStart事件,并提取路径正确的URL参数开头 / URL /

  3. 连接code正确的URL参数角兼容的形式(在这种特殊情况下,我使用的base64)。不要使用EN codeURIComponent,因为角度将视为任何其他网址

  4. 重定向到与您的业务逻辑,例如另一条路线。 site.com/parsed-url/BASE64_GOES_HERE

  5. 德code控制器中的网址,并使用它像往常一样:)

code

创建角应用模块照常

  angular.module('路线',[])。配置([  '$ routeProvider',  功能($ routeProvider){
    $ routeProvider
      。当('/测试',{templateUrl:test.html的'})
      //这个是很重要的:
      //我们定义将在内部使用和处理路线
      //经由URLInterceptor服务由我们解析的URL参数
      。当('/解析-URL /:URL',{templateUrl:url.html',控制器:'URLCtrl'})
      。当('/',{redirectTo:'/测试'})
      不然的话({templateUrl:'404.html'});  }])

URL拦截器服务(单身)

 。服务('URLInterceptor',函数($ rootScope,$位置){
  //我们倾听$ routeChangeStart事件,如果拦截
  //路径我们的URL方案相匹配。在这种情况下,每一个路由
  //用/ URL开始/必被捉
  $ rootScope。在$('$ routeChangeStart'功能(即,接下来,电流){    // $ location.path没有改变之前实际路由情况,
    //所以在这种情况下,我们得到解析新的位置对象
    // 免费。    //要珩磨机,处理这种情况下,更好的方法可能会使用
    // $ locationChangeStart事件,而不是,但它需要我们来解析的网址
    手动//。
    VAR PATH = $ location.path();
    //检查字符串'/ URL /开头
    变种匹配= path.slice(0,5);
    VAR则cleanpath ='';
    如果(匹配==='/ URL /'){
      //是它,耶!
      //删除前导'/ URL /'来提取实际参数
      则cleanpath = path.slice(5);
      // EN code我们的网址到安全版本。我们知道,恩codeURIComponent不会
      //无论是工作,所以一个好的选择可能为Base64。
      //我使用https://$c$c.google.com/p/javascriptbase64/downloads
      $ location.path('/解析-URL /+ Base64.en code(则cleanpath));
      // prevent默认事件执行。需要注意的是,它不会取消相关$位置活动
      亦即preventDefault();
    }
  });  返回{
    德code:Base64.de code,
    EN code:Base64.en code
  }
})

控制器

  //主要应用控制器
//我们在这里实例化URLInterceptor服务
.controller('AppCtrl',函数($范围,$位置,URLInterceptor){
  $ scope.navigateTo =功能(路径){
    $ location.path('/ URL /'+路径);
  }
})
.controller('URLCtrl',函数($范围,$ routeParams,URLInterceptor){
  $ scope.url = URLInterceptor.de code($ routeParams.url);
});

两件事情你应该记住:


  1. 虽然我试图创建一个解决方案,尽可能的干净,通常是通过这种方式来角不被认为是一个很好的做法中的数据,所以尽量不要使用它,除非你真的需要。

  2. 您可以处理这个问题只有一个途径。我只是觉得它更清洁的这种方式。

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://paprikka.github.io/le-bat/#/preview/http://page.com

neither will this: http://paprikka.github.io/le-bat/#/preview/http%3A%2F%2Fpage.com

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

Details

AngularJS routing mechanism by its design does not allow to pass strings with slashes as query parameters. I can understand the reasoning behind this decision - we don't want to create a stateless server here.

However, there are still cases when using different separators or regular expressions in routes might be necessary.

I wanted to create an app that takes a url hash string parameter and loads its content to an iframe (link here). Routes are set up in pretty standard way (I'm using Coffeescript, but this snippet does not differ from pure js):

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

Of course, I can load url from hash before AngularJS gets bootstrapped and then pass it to the library, but it would be nice if I could also update current route parameter when changing data in scope - that's why I think it's much better not to avoid AngularJS API.

解决方案

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.

这篇关于通过网址为$ routeParam在AngularJS应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆