Comment définir un attribut src iframe à partir d'une variable dans AngularJS

214

J'essaie de définir l' srcattribut d'un iframe à partir d'une variable et je ne peux pas le faire fonctionner ...

Le balisage:

<div class="col-xs-12" ng-controller="AppCtrl">

    <ul class="">
        <li ng-repeat="project in projects">
            <a ng-click="setProject(project.id)" href="">{{project.url}}</a>
        </li>
    </ul>

    <iframe  ng-src="{{trustSrc(currentProject.url)}}">
        Something wrong...
    </iframe>
</div>

controllers / app.js:

function AppCtrl ($scope) {

    $scope.projects = {

        1 : {
            "id" : 1,
            "name" : "Mela Sarkar",
            "url" : "http://blabla.com",
            "description" : "A professional portfolio site for McGill University professor Mela Sarkar."
        },

        2 : {
            "id" : 2,
            "name" : "Good Watching",
            "url" : "http://goodwatching.com",
            "description" : "Weekend experiment to help my mom decide what to watch."    
        }
    };

    $scope.setProject = function (id) {
        $scope.currentProject = $scope.projects[id];
        console.log( $scope.currentProject );

    }
}

Avec ce code, rien n'est inséré dans l' srcattribut iframe . C'est juste vide.

Mise à jour 1: j'ai injecté la $scedépendance dans AppCtrl et $ sce.trustUrl () fonctionne maintenant sans lancer d'erreurs. Cependant, il retourne TrustedValueHolderTypeque je ne sais pas comment utiliser pour insérer une URL réelle. Le même type est renvoyé si j'utilise $ sce.trustUrl () à l'intérieur des accolades d'interpolation dans l'attribut src="{{trustUrl(currentProjectUrl))}}"ou si je le fais à l'intérieur du contrôleur lors de la définition de la valeur de currentProjectUrl. Je l'ai même essayé avec les deux.

Mise à jour 2: j'ai compris comment renvoyer l'URL du trustedUrlHolder à l'aide de .toString () mais quand je le fais, il lance l'avertissement de sécurité lorsque j'essaie de le passer dans l'attribut src.

Mise à jour 3: cela fonctionne si j'utilise trustAsResourceUrl () dans le contrôleur et le transmets à une variable utilisée dans l'attribut ng-src:

$scope.setProject = function (id) {
    $scope.currentProject = $scope.projects[id];
    $scope.currentProjectUrl = $sce.trustAsResourceUrl($scope.currentProject.url);
    console.log( $scope.currentProject );
    console.log( $scope.currentProjectUrl );

}

Mon problème semble être résolu par cela, même si je ne sais pas trop pourquoi.

emersonthis
la source

Réponses:

360

Je soupçonne regardant l'extrait que la fonction trustSrcde trustSrc(currentProject.url)n'est pas définie dans le contrôleur.

Vous devez injecter le $sceservice dans le contrôleur et là trustAsResourceUrl- urlbas.

Dans le contrôleur:

function AppCtrl($scope, $sce) {
    // ...
    $scope.setProject = function (id) {
      $scope.currentProject = $scope.projects[id];
      $scope.currentProjectUrl = $sce.trustAsResourceUrl($scope.currentProject.url);
    }
}

Dans le modèle:

<iframe ng-src="{{currentProjectUrl}}"> <!--content--> </iframe>
musically_ut
la source
1
Je l'ai essayé avec $ sce comme vous l'avez recommandé. Cela provoque la disparition du message d'erreur, mais l'attribut src de l'iframe est toujours vide.
emersonthis
3
Essayez d'utiliser trustAsResourceUrl.
musically_ut
9
... mais celui-ci fonctionne quand je le passe dans l'attribut ng-src! Merci.
emersonthis
2
@Emerson trustAsResourceUrlretourne un $sce.RESOURCE_URLqui est nécessaire pour iframe/ objectstandis que trustAsUrlrenvoie un $sce.URLqui est une sorte de garantie plus faible (et qui n'est actuellement pas utilisé selon la documentation ).
musically_ut
1
ng-src n'a pas fonctionné pour moi à moins que je ne supprime les doubles accolades (ng-src = "currentProjectUrl")
baacke
10

C'est le $sceservice qui bloque les URL avec des domaines externes, c'est un service qui fournit des services d'échappement contextuel strict à AngularJS, pour prévenir les failles de sécurité telles que XSS, le détournement de clics, etc. il est activé par défaut dans Angular 1.2.

Vous pouvez le désactiver complètement, mais ce n'est pas recommandé

angular.module('myAppWithSceDisabledmyApp', [])
   .config(function($sceProvider) {
       $sceProvider.enabled(false);
   });

pour plus d'informations https://docs.angularjs.org/api/ng/service/$sce

Mohamed Selim
la source
3

de cette façon, je suis et son travail pour moi très bien, que cela fonctionne pour vous,

<iframe class="img-responsive" src="{{pdfLoc| trustThisUrl }}" ng-style="{
                height: iframeHeight * 0.75 + 'px'
            }" style="width:100%"></iframe>

ici trustThisUrl est juste un filtre,

angular.module("app").filter('trustThisUrl', ["$sce", function ($sce) {
        return function (val) {
            return $sce.trustAsResourceUrl(val);
        };
    }]);
chandrakant
la source
2

Veuillez supprimer l'appel à la trustSrcfonction et réessayer comme ceci. {{trustSrc (currentProject.url)}} à {{currentProject.url}}. Vérifiez ce lien http://plnkr.co/edit/caqS1jE9fpmMn5NofUve?p=preview


Mais selon la documentation Angular Js 1.2, vous devez écrire une fonction pour obtenir l' srcurl. Jetez un oeil sur le code suivant.

Avant:

Javascript

scope.baseUrl = 'page';
scope.a = 1;
scope.b = 2;

Html

<!-- Are a and b properly escaped here? Is baseUrl controlled by user? -->
<iframe src="{{baseUrl}}?a={{a}&b={{b}}"

Mais pour des raisons de sécurité, ils recommandent la méthode suivante

Javascript

var baseUrl = "page";
scope.getIframeSrc = function() {

  // One should think about their particular case and sanitize accordingly
  var qs = ["a", "b"].map(function(value, name) {
      return encodeURIComponent(name) + "=" +
             encodeURIComponent(value);
    }).join("&");

  // `baseUrl` isn't exposed to a user's control, so we don't have to worry about escaping it.
  return baseUrl + "?" + qs;
};

Html

<iframe src="{{getIframeSrc()}}">
Sajith
la source
La documentation fournit ces conseils dans le cas où une liaison à plusieurs expressions dans ng-srcou src. Angular 1.2 en avant, on peut se lier à une seule expression dans srcet ng-srcet le conseil est de récupérer une URL du code en utilisant une fonction, si nécessaire.
musically_ut
Mais je pense qu'il y a une erreur dans votre code. Le contrôleur doit être comme ce app.controller ('AppCtrl', function ($ scope) {});
Sajith
1
Les contrôleurs peuvent également être des fonctions accessibles à l'échelle mondiale .
musically_ut
D'accord. Vérifiez ce lien J'ai vérifié votre code avec plunker. plnkr.co/edit/caqS1jE9fpmMn5NofUve
Sajith
J'ai remarqué une fonction "trustSrc" dans votre code. Veuillez supprimer cette fonction et réessayer comme ceci. {{trustSrc (currentProject.url)}} à {{currentProject.url}}
Sajith
0

sélectionner un modèle; contrôleur iframe, mise à jour du modèle ng

index.html

angularapp.controller('FieldCtrl', function ($scope, $sce) {
        var iframeclass = '';
        $scope.loadTemplate = function() {
            if ($scope.template.length > 0) {
                // add iframe classs
                iframeclass = $scope.template.split('.')[0];
                iframe.classList.add(iframeclass);
                $scope.activeTemplate = $sce.trustAsResourceUrl($scope.template);
            } else {
                iframe.classList.remove(iframeclass);
            };
        };

    });
    // custom directive
    angularapp.directive('myChange', function() {
        return function(scope, element) {
            element.bind('input', function() {
                // the iframe function
                iframe.contentWindow.update({
                    name: element[0].name,
                    value: element[0].value
                });
            });
        };
    });

iframe.html

   window.update = function(data) {
        $scope.$apply(function() {
            $scope[data.name] = (data.value.length > 0) ? data.value: defaults[data.name];
        });
    };

Vérifiez ce lien: http://plnkr.co/edit/TGRj2o?p=preview

Osman Selvi
la source
0

Vous devez également $sce.trustAsResourceUrlou il n'ouvrira pas le site Web à l'intérieur de l'iframe:

angular.module('myApp', [])
    .controller('dummy', ['$scope', '$sce', function ($scope, $sce) {

    $scope.url = $sce.trustAsResourceUrl('https://www.angularjs.org');

    $scope.changeIt = function () {
        $scope.url = $sce.trustAsResourceUrl('https://docs.angularjs.org/tutorial');
    }
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="myApp" ng-controller="dummy">
    <iframe ng-src="{{url}}" width="300" height="200"></iframe>
    <br>
    <button ng-click="changeIt()">Change it</button>
</div>

Abdo-Host
la source