Подтвердить что ты не робот

Множественные выражения AngularJS, конкатенирующие в интерполяции с URL-адресом

Я знаю, что это долго, но, пожалуйста, несите меня. Проблема легко понять, просто требуется письменность, чтобы полностью объяснить ее.

Сейчас я получаю эту ошибку

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

Я все прочитал в документации, но я все еще не могу найти обходной путь для своей проблемы.

Я использую $http.get в частном онлайн-источнике, который имеет данные, похожие на форму json файла (поэтому я не могу изменять данные). Данные выглядят следующим образом:

...
"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"
       },
    },
...

Я пытаюсь интерполировать videoId каждого элемента в свой HTML iframe, который включает видео YouTube. В моем файле controller.js я устанавливаю объект обещания после $http.get как такового

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

Итак, теперь переменная "$ scope.videoList" сопоставляется с data.items, в которой много видеоэлементов. В моем файле HTML я могу получить идентификатор видео каждого видео с помощью

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

и в нем перечислены все идентификаторы видео. Но если я попытаюсь связать эти значения с URL-адресом, например https://youtube.com/embed/, это не сработает.

<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 для интерполирования в URL-адрес youtube? Я попытался использовать белый список с помощью $sceDelegateProvider следующим образом, но он все еще не работает.

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

Любая помощь приветствуется. Спасибо!

4b9b3361

Ответ 1

Начиная с 1.2, вы можете привязать только одно выражение к * [src], * [ng-src] или к действию. Вы можете прочитать об этом здесь.

Попробуйте это вместо:

В контроллере:

$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.

Ответ 2

Альтернативой ответом @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-значков, для чего вам нужно использовать атрибут xlink:href в теге SVG use - это относится к тем же правилам SCE. Повторение функции контроллера везде, где мне нужно было использовать спрайт, казалось глупым, поэтому я использовал метод фильтра.

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, я выбрал фильтр, который, похоже, решил проблему.

Ответ 3

в контроллере:

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"

Ответ 4

Моя версия angular.min.1.5.8.js У меня была такая же проблема с формой. Я разрешил его, изменив атрибут action = URL по адресу ng-action = URL.