AngularJS 多个表达式与 URL 插值连接

IT技术 javascript angularjs youtube concatenation interpolation
2021-02-19 07:54:26

我知道这很长,但请耐心等待。这个问题很容易理解,只需要写一些文字来充分解释它。

现在我收到这个错误

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 插入到嵌入 YouTube 视频的 HTML iframe 中。在我的 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。但是,如果我尝试将这些值连接到一个 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 插入到 youtube URL 中?我已经尝试使用 $sceDelegateProvider 将其列入白名单,如下所示,但它仍然不起作用

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

任何帮助表示赞赏。谢谢!

4个回答

@tasseKATT 的答案(不需要控制器函数)的替代方法是直接在表达式a 过滤器中使用字符串连接

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:hrefSVGuse标签上的属性- 这受相同的 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等效项,我选择了过滤器,这似乎解决了问题。usexlink:href

感谢您的解决方案。如果xlink:href有任何字符串连接,如xlink:href="/path/to/something/{{ type.key | svgIconCardHref }}".
2021-04-25 07:54:26
您可以尝试将静态字符串放在 curl 中: xlink:href="{{ '/path/to/something/' + (type.key | svgIconCardHref) }}"
2021-05-01 07:54:26

从 1.2 开始,您只能将一个表达式绑定到 *[src]、*[ng-src] 或 action。您可以在此处阅读更多相关信息

试试这个:

在控制器中:

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

+1 并感谢您的回答,因为所有其他答案都依赖于将 URL 硬编码为 $sce 受信任资源,而不是将其填充为模板项。
2021-04-22 07:54:26
谢谢。你如何将网址列入白名单?
2021-04-24 07:54:26
@molerat 通过$sceDelegateProvider在配置块中注入和使用例如:$sceDelegateProvider.resourceUrlWhitelist(['self', 'https://www.youtube.com/**']);
2021-05-04 07:54:26
@tasseKATT 谢谢 - 我刚刚看到这已经在问题中了 :)
2021-05-09 07:54:26

在控制器中:

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"

我的版本是angular.min.1.5.8.js 我在表单上遇到了同样的问题。我通过将属性 action=URL 更改为 ng-action=URL 来解决它。

注意:这不起作用,因为ng-action它不是真正的指令。