web-dev-qa-db-fra.com

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

J'essaie de définir l'attribut src d'une iframe à partir d'une variable et je n'arrive 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'attribut src de l'iframe. C'est juste vide.

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

Mise à jour 2: J'ai découvert comment renvoyer l'URL de trustedUrlHolder à l'aide de .toString (), mais lorsque je le fais, il envoie l'avertissement de sécurité lorsque je tente de le transmettre dans l'attribut src.

Mise à jour 3: Cela fonctionne si j'utilise trustAsResourceUrl () dans le contrôleur et que je le passe à 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 ceci, bien que je ne sois pas tout à fait pourquoi.

204
emersonthis

Je suspecte de regarder dans l'extrait que la fonction trustSrc de trustSrc(currentProject.url) n'est pas définie dans le contrôleur. 

Vous devez injecter le $sce service dans le contrôleur et trustAsResourceUrl la url.

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

C’est le service $ sce qui bloque les URL avec les domaines externes, c’est un service qui fournit des services d’échappement contextuel strict à AngularJS, afin de 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

11
Mohamed Selim

Veuillez supprimer l'appel à la fonction trustSrc 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 de Js 1.2 angulaire, vous devriez écrire une fonction permettant d’obtenir src url. Regardez 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()}}">
2
Sajith

de cette façon, je suis et son travail pour moi va bien, que ça marche 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);
        };
    }]);
1
chandrakant

Vous devez également utiliser $sce.trustAsResourceUrl ou le site Web à l'intérieur de l'iframe ne sera pas ouvert:

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>

0
Abdo-Host

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

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

0
Osman Selvi