16

実際の URL (スラッシュ、カンマなどを含む) を $routeParam として AngularJS アプリに渡すにはどうすればよいですか?

これは動作します: 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'})

もちろん、AngularJS がブートストラップされる前にハッシュから URL を読み込んでライブラリに渡すこともできますが、スコープ内のデータを変更するときに現在のルート パラメータも更新できると便利です。 AngularJS API。

4

4 に答える 4

17

Angular 1.2 で$routeProviderを使用すると、パターンにアスタリスクを追加することで、パスの末尾にある場合に URL を渡すことができます。以下は、URL を URLComponentEncode するかどうかに関係なく機能するはずです。

ルート:

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>
于 2013-11-19T06:12:57.567 に答える
5

OK、現在の安定版(@ 1.0.7)で動作するソリューションを見つけることができました。

この問題を処理する現在の方法には、$route 関連のイベントが含まれ、Angular と互換性のない URL をオンザフライで解析し、$http インターセプトと同様の方法で機能する追加のサービスを介してそれらを処理します。

ここで実際のコード例を見ることができます: http://embed.plnkr.co/fIA2xj/preview

主な手順

  1. いつものように角度互換性のないURLを渡します。site.com/url/ http://site.comにアクセスしてください
  2. $routeChangeStart イベントをリッスンし、で始まるパスの正しい URL パラメータを抽出します/url/
  3. 正しい url パラメーターを角度互換の形式にエンコードします (この特定のケースでは、base64 を使用します)。angular は他の URL として扱われるため、encodeURIComponent を使用しないでください。
  4. ビジネスロジックを使用して別のルートにリダイレクトします。site.com/parsed-url/BASE64_GOES_HERE
  5. コントローラーで URL をデコードし、通常どおり使用します :)

コード

いつものようにangularアプリモジュールを作成する

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

覚えておくべき 2 つのこと:

  1. できるだけクリーンなソリューションを作成しようとしましたが、通常、この方法でデータを angular に渡すことは良い習慣とは見なされないため、本当に必要でない限り使用しないようにしてください。
  2. この問題は、1 つのルートだけで処理できます。私はちょうどそれがこのようにきれいだと思います。
于 2013-08-04T12:56:37.667 に答える
0

検索パラメータとルートを混在させました。特に古いブラウザの場合は、ルートの前に検索を行う必要があります。そうでない場合、ie7が爆発すると思いますurl/?search/#/hash

このフォーマットを試してください:

domain.com/?my=params&another=param/#/my/hashes
于 2013-07-27T01:53:42.930 に答える