web-dev-qa-db-fra.com

AngularJS expressions multiples concaténant en interpolation avec une URL

Je sais que c'est long, mais s'il te plaît, supporte-moi. Le problème est facile à comprendre, il suffit d’écrire pour bien l'expliquer.

En ce moment je reçois cette erreur

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

J'ai lu toute la documentation, mais je ne trouve toujours pas de solution de contournement à mon problème.

J'utilise $ http.get sur une source privée en ligne dont les données sont similaires à la forme d'un fichier JSON (je ne peux donc pas modifier les données). Les données ressemblent à ceci:

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

J'essaie d'interpoler le videoId de chaque élément dans mon iframe HTML qui incorpore la vidéo YouTube. Dans mon fichier controller.js, je mets l'objet de promesse après le $ http.get en tant que tel

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

Alors maintenant, la variable "$ scope.videoList" est mappée sur data.items, qui contient de nombreux éléments vidéo. Dans mon fichier HTML, je peux récupérer le videoID de chaque vidéo en utilisant

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

et cela répertorie tous les ID vidéo. Mais si j'essaie de concaténer ces valeurs dans une URL, telle que https://youtube.com/embed/ , cela ne fonctionne pas.

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

Existe-t-il un moyen d'obtenir l'interpolation de videoID dans l'URL youtube? J'ai essayé la liste blanche en utilisant $ sceDelegateProvider comme suit, mais cela ne fonctionne toujours pas

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

Toute aide est appréciée. Merci!

44
user2669464

Depuis 1.2, vous ne pouvez associer qu'une seule expression à * [src], * [ng-src] ou à une action. Vous pouvez en lire plus à ce sujet ici .

Essayez ceci à la place:

En contrôleur:

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

HTML:

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

Notez que vous devez toujours ajouter la liste blanche à votre liste, sinon vous obtiendrez locked loading resource from url not allowed by $sceDelegate policy.

57
tasseKATT

Une alternative à la réponse de @ tasseKATT (qui ne nécessite pas de fonction de contrôleur) est d’utiliser concaténation de chaînes directement dans l'expression un filtre:

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>

J'ai trouvé cela particulièrement utile lorsque vous utilisez des sprites d'icônes SVG, ce qui vous oblige à utiliser l'attribut xlink:href de la balise SVG use - elle est soumise aux mêmes règles SCE. Répéter la fonction de contrôleur partout où je devais utiliser un Sprite me paraissait idiot alors j'ai utilisé la méthode du filtre.

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>

Remarque: j'avais précédemment essayé une simple concaténation de chaînes dans l'expression. Cependant, cela a conduit à un comportement inattendu dans lequel le navigateur interprétait l'expression avant qu'Angular ait une chance de l'analyser et de la remplacer par la valeur réelle href. Puisqu'il n'y a pas d'équivalent ng-src pour le xlink:href de la balise use, j'ai opté pour le filtre, ce qui semble avoir résolu le problème.

76
Tom Spencer

dans le contrôleur: 

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

en html: 

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

Ma version est angular.min.1.5.8.js J'ai eu le même problème avec un formulaire. Je l'ai résolu en changeant l'attribut action = URL par ng-action = URL.

0
Francisco