Jak ustawić atrybut src iframe ze zmiennej w AngularJS

214

Próbuję ustawić srcatrybut iframe ze zmiennej i nie mogę go uruchomić ...

Znaczniki:

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

kontrolery / 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 );

    }
}

Dzięki temu kodowi nic nie jest wstawiane do srcatrybutu iframe . To jest po prostu puste.

Aktualizacja 1: wstrzyknąłem $scezależność do AppCtrl i $ sce.trustUrl () działa teraz bez zgłaszania błędów. Zwraca jednak informacje, TrustedValueHolderTypektórych nie jestem pewien, jak wstawić rzeczywisty adres URL. Ten sam typ jest zwracany bez względu na to, czy używam $ sce.trustUrl () wewnątrz nawiasów interpolacyjnych w atrybucie, src="{{trustUrl(currentProjectUrl))}}"czy robię to wewnątrz kontrolera podczas ustawiania wartości currentProjectUrl. Próbowałem nawet z obydwoma.

Aktualizacja 2: Zorientowałem się, jak zwrócić adres URL z zaufanegoUrlHolder za pomocą .toString (), ale kiedy to robię, wyświetla ostrzeżenie bezpieczeństwa, gdy próbuję przekazać go do atrybutu src.

Aktualizacja 3: Działa, jeśli użyję trustAsResourceUrl () w kontrolerze i przekażę to do zmiennej używanej w atrybucie 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 );

}

Wydaje się, że mój problem został przez to rozwiązany, chociaż nie jestem do końca pewien, dlaczego.

emersonthis
źródło

Odpowiedzi:

360

I podejrzewam patrząc na fragmencie, że funkcja trustSrcz trustSrc(currentProject.url)nie jest zdefiniowana w kontrolerze.

Trzeba wstrzyknąć $sceusługę w kontrolerze i tam.trustAsResourceUrlurl

W kontrolerze:

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

W szablonie:

<iframe ng-src="{{currentProjectUrl}}"> <!--content--> </iframe>
muzycznie
źródło
1
Próbowałem z $ sce zgodnie z zaleceniami. Powoduje to zniknięcie komunikatu o błędzie, ale atrybut src elementu iframe jest nadal pusty.
emersonthis
3
Spróbuj użyć trustAsResourceUrl.
musically_ut,
9
... ale ten działa, gdy przekażę go do atrybutu ng-src! Dzięki.
emersonthis
2
@ Emerson trustAsResourceUrlzwraca element $sce.RESOURCE_URLniezbędny do iframe/ objectspodczas trustAsUrlzwrotu, $sce.URLktóry jest słabszym rodzajem gwarancji (i obecnie nie jest używany zgodnie z dokumentacją ).
musically_ut
1
ng-src nie działało dla mnie, chyba że
usunę
10

Jest to $sceusługa, która blokuje adresy URL z domenami zewnętrznymi, jest to usługa zapewniająca AngularJS ścisłe kontekstowe ucieczkę, aby zapobiec lukom w zabezpieczeniach, takim jak XSS, clickjacking itp., Jest ona domyślnie włączona w Angular 1.2.

Możesz go całkowicie wyłączyć, ale nie jest to zalecane

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

aby uzyskać więcej informacji https://docs.angularjs.org/api/ng/service/$sce

Mohamed Selim
źródło
3

w ten sposób podążam i jego praca jest dla mnie w porządku, oby to zadziałało dla ciebie,

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

tutaj trustThisUrl to tylko filtr,

angular.module("app").filter('trustThisUrl', ["$sce", function ($sce) {
        return function (val) {
            return $sce.trustAsResourceUrl(val);
        };
    }]);
Chandrakant
źródło
2

Usuń połączenie z trustSrcfunkcją i spróbuj ponownie w ten sposób. {{trustSrc (currentProject.url)}} do {{currentProject.url}}. Sprawdź ten link http://plnkr.co/edit/caqS1jE9fpmMn5NofUve?p=preview


Ale zgodnie z dokumentacją Angular Js 1.2 powinieneś napisać funkcję pobierania srcadresu URL. Spójrz na następujący kod.

Przed:

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

Ale ze względów bezpieczeństwa zalecają następującą metodę

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
źródło
Dokumentacja zawiera te porady w przypadku, gdy wiąże się więcej niż jedno wyrażenie w ng-srclub src. Począwszy od wersji 1.2, można powiązać tylko jedno wyrażenie w srci ng-srczaleca się, aby w razie potrzeby pobrać adres URL z kodu za pomocą funkcji.
musically_ut
Ale myślę, że jest jakiś błąd w twoim kodzie. Kontroler powinien być taki jak ten app.controller ('AppCtrl', function ($ scope) {});
Sajith,
1
Kontrolery mogą być również funkcjami dostępnymi na całym świecie .
musically_ut,
Dobrze. Sprawdź ten link Sprawdziłem twój kod za pomocą narzędzia plunker. plnkr.co/edit/caqS1jE9fpmMn5NofUve
Sajith
W twoim kodzie zauważyłem funkcję „trustSrc”. Usuń tę funkcję i spróbuj ponownie w ten sposób. {{trustSrc (currentProject.url)}} do {{currentProject.url}}
Sajith
0

wybierz szablon; kontroler iframe, aktualizacja modelu

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];
        });
    };

Sprawdź ten link: http://plnkr.co/edit/TGRj2o?p=preview

Osman Selvi
źródło
0

Potrzebujesz także, $sce.trustAsResourceUrlbo inaczej nie otworzy strony internetowej w ramce 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
źródło