web-dev-qa-db-ja.com

URLとの補間で連結するAngularJSの複数の式

私はこれが長いことを知っていますが、私と一緒に耐えてください。問題を理解するのは簡単で、それを完全に説明するためにいくつかの文章を書くだけです。

今、私はこのエラーを受け取っています

Error: [$interpolate:noconcat] Error while interpolating: 
Strict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required.  
See http://docs.angularjs.org/api/ng.$sce

ドキュメントのすべての読み取りを完了しましたが、問題の回避策がまだ見つかりません。

Jsonファイルの形式に似たデータを持つプライベートなオンラインソースで$ http.getを使用しています(データを変更できません)。データは次のようになります。

...
"items": [
  {
   "kind": "youtube#searchResult",
   "etag": "\"N5Eg36Gl054SUNiWWc-Su3t5O-k/A7os41NAa_66TUu-1I-VxH70Rp0\"",
   "id": {
      "kind": "youtube#video",
      "videoID": "MEoSax3BEms"
      },
   },
   {
    "kind": "youtube#searchResult",
    "etag": "\"N5Eg36Gl054SUNiWWc-Su3t5O-k/VsH9AmnQecyYBLJrl1g3dhewrQo\"",
    "id": {
       "kind": "youtube#video",
       "videoID": "oUBqFlRjVXU"
       },
    },
...

YouTubeビデオを埋め込むHTML iframeに各アイテムのvideoIdを補間しようとしています。私のcontroller.jsファイルでは、$ http.getの後にpromiseオブジェクトを設定しています

$http.get('privatesource').success(function(data) {
  $scope.videoList = data.items;
});

そのため、変数「$ scope.videoList」は、多くのビデオ要素を持つdata.itemsにマップされます。 HTMLファイルでは、次を使用して各ビデオのvideoIDを取得できます。

<ul class="videos">
  <li ng-repeat="video in videoList">
    <span>{{video.id.videoID}}</span>
  </li>
</ul>

これにはすべてのvideoIDがリストされます。しかし、これらの値を https://youtube.com/embed/ などのURLに連結しようとすると、機能しません。

<div ng-repeat="video in videoList">
    <iframe id="ytplayer" type="text/html" width="640" height="360" 
     ng-src="https://www.youtube.com/embed/{{video.id.videoId}}" 
     frameborder="0" allowfullscreen></iframe>
</div>

VideoIDをyoutube URLに挿入する方法はありますか?次のように$ sceDelegateProviderを使用してホワイトリストに登録しようとしましたが、まだ機能しません

$sceDelegateProvider.resourceUrlWhitelist([
  'self',
  'https://www.youtube.com/**']);

どんな助けも大歓迎です。ありがとう!

44
user2669464

1.2以降では、* [src]、* [ng-src]、またはactionにバインドできる式は1つだけです。詳しくは こちら をご覧ください。

代わりにこれを試してください:

コントローラー内:

$scope.getIframeSrc = function (videoId) {
  return 'https://www.youtube.com/embed/' + videoId;
};

HTML:

ng-src="{{getIframeSrc(video.id.videoId)}}"

ホワイトリストに登録する必要があることに注意してください。そうしないと、locked loading resource from url not allowed by $sceDelegate policy

57
tasseKATT

@tasseKATTの回答(コントローラー関数を必要としない)の代替手段は、 式での直接の文字列連結 フィルター:

_angular.module('myApp')
  .filter('youtubeEmbedUrl', function ($sce) {
    return function(videoId) {
      return $sce.trustAsResourceUrl('http://www.youtube.com/embed/' + videoId);
    };
  });
_
_<div ng-src="{{ video.id.videoId | youtubeEmbedUrl }}"></div>
_

これは、SVG useタグで_xlink:href_属性を使用する必要があるSVGアイコンスプライトを使用するときに特に便利であることがわかりました。これは同じSCEルールに従います。 Spriteを使用する必要があるすべての場所でコントローラー関数を繰り返すことはばかげているように思えたので、代わりにフィルターメソッドを使用しました。

_angular.module('myApp')
  .filter('svgIconCardHref', function ($sce) {
    return function(iconCardId) {
      return $sce.trustAsResourceUrl('#s-icon-card-' + iconCardId);
    };
  });
_
_<svg><use xlink:href="{{ type.key | svgIconCardHref }}"></use></svg>
_

注:以前、式内で単純な文字列の連結を試みました。しかし、これにより、ブラウザがAngular=がそれを解析し、実際のhrefに置き換える機会を持つ前に式を解釈するという予期しない動作を引き起こしました。_ng-src_ useタグの_xlink:href_と同等フィルターを選択しましたが、これで問題が解決したようです。

77
Tom Spencer

コントローラー内:

app.filter('trustAsResourceUrl', ['$sce', function ($sce) {
    return function (val) {
        return $sce.trustAsResourceUrl(val);
    };
}]);

hTMLで:

ng-src="('https://www.youtube.com/embed/' + video.id.videoId) | trustAsResourceUrl"
2
Serge

私のバージョンはangular.min.1.5.8.jsフォームにも同じ問題がありました。 ng-action = URLによって属性action = URLを変更することで解決しました。

0
Francisco