Множественные выражения 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/**']);
Любая помощь приветствуется. Спасибо!
Ответы
Ответ 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.