web-dev-qa-db-ja.com

AngularJSアプリで$ routeParamとしてURLを渡します

実際の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。

16
Rafal Pastuszak

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

この問題を処理する現在の方法には、$ route関連のイベントが含まれ、角度に互換性のない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 app moduleを作成します

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('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つのルートでのみ処理できます。私はそれがこのようにすっきりしていると思います。
5
Rafal Pastuszak

$ routeProvider in Angular 1.2を使用すると、パターンにアスタリスクを追加することにより、パスの最後にある場合、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>
17
mattwad

私には解決策がありますが、それがあなたを助けるかどうかはわかりません。 From Angular documention http://docs.angularjs.org/api/ng 。$ location $ location has a function search(search、paramValue)

パラメータを渡すには:

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

パラメータを読み取るには:

url = decodeURIComponent $location.search().yourURLParameter

もちろん$ location依存関係を注入する必要があります

1
jtello

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

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

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