【问题标题】:How to set an iframe src attribute from a variable in AngularJS如何从 AngularJS 中的变量设置 iframe src 属性
【发布时间】:2013-12-01 10:44:33
【问题描述】:

我正在尝试从一个变量设置 iframe 的 src 属性,但我无法让它工作...

标记:

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

控制器/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 );

    }
}

使用此代码,iframe 的src 属性中不会插入任何内容。它只是空白。

更新 1: 我将 $sce 依赖注入到 AppCtrl 和 $sce.trustUrl() 现在可以正常工作而不会引发错误。但是它返回TrustedValueHolderType,我不确定如何使用它来插入实际的 URL。无论我在属性src="{{trustUrl(currentProjectUrl))}}" 的插值括号内使用$sce.trustUrl() 还是在设置currentProjectUrl 的值时在控制器内使用它,都会返回相同的类型。我什至都试过了。

更新 2: 我想出了如何使用 .toString() 从trustedUrlHolder 返回url,但是当我这样做时,当我尝试将它传递给src 属性时它会引发安全警告。

更新 3: 如果我在控制器中使用 trustAsResourceUrl() 并将其传递给 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 );

}

我的问题似乎由此解决了,虽然我不太清楚为什么。

【问题讨论】:

    标签: javascript html angularjs iframe angularjs-directive


    【解决方案1】:

    我怀疑在查看摘录时,trustSrc(currentProject.url) 中的函数 trustSrc 未在控制器中定义。

    您需要在控制器中注入$sce service,并在那里注入trustAsResourceUrl url

    在控制器中:

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

    在模板中:

    <iframe ng-src="{{currentProjectUrl}}"> <!--content--> </iframe>
    

    【讨论】:

    • 我按照您的建议使用 $sce 进行了尝试。它会导致错误消息消失,但 iframe 的 src 属性仍然为空。
    • 尝试使用trustAsResourceUrl
    • ...但是当我将它传递给 ng-src 属性时,这个可以工作!谢谢。
    • @Emerson trustAsResourceUrl 返回一个$sce.RESOURCE_URL,这是iframe/objects 所需要的,而trustAsUrl 返回一个$sce.URL,这是一种较弱的保证(目前未使用)根据the documentation)。
    • ng-src 对我不起作用,除非我删除了双花括号(ng-src="currentProjectUrl")
    【解决方案2】:

    请删除对trustSrc 函数的调用,然后像这样重试。 {{trustSrc(currentProject.url)}} 到 {{currentProject.url}}。 检查此链接http://plnkr.co/edit/caqS1jE9fpmMn5NofUve?p=preview


    但是根据 Angular Js 1.2 文档,您应该编写一个函数来获取src url。看看下面的代码。

    之前:

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

    但出于安全原因,他们推荐以下方法

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

    【讨论】:

    • 文档提供了这个建议,以防绑定到ng-srcsrc 中的多个表达式。从 Angular 1.2 开始,可以只绑定到 srcng-src 中的一个表达式,如果需要,建议使用函数从代码中检索 url。
    • 但是我认为你的代码有一些错误。控制器应该像这样 app.controller('AppCtrl', function($scope) {});
    • 控制器也可以是Globally accessible functions
    • 好的。检查这个链接我用 plunker 检查了你的代码。 plnkr.co/edit/caqS1jE9fpmMn5NofUve
    • 我注意到您的代码中有一个函数“trustSrc”。请删除该功能,然后再试一次。 {{trustSrc(currentProject.url)}} 到 {{currentProject.url}}
    【解决方案3】:

    选择模板; iframe 控制器,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];
            });
        };
    

    查看此链接:http://plnkr.co/edit/TGRj2o?p=preview

    【讨论】:

      【解决方案4】:

      $sce 服务可以阻止带有外部域的 URL,它是一种为 AngularJS 提供严格上下文转义服务的服务,以防止 XSS、点击劫持等安全漏洞。它在 Angular 1.2 中默认启用。

      您可以完全禁用它,但不建议这样做

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

      了解更多信息 https://docs.angularjs.org/api/ng/service/$sce

      【讨论】:

        【解决方案5】:

        我遵循这种方式,它对我来说很好,希望它对你有用,

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

        这里 trustThisUrl 只是过滤器,

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

        【讨论】:

          【解决方案6】:

          您还需要$sce.trustAsResourceUrl 否则将无法在 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>

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-12-16
            • 2011-11-24
            • 2017-12-13
            • 1970-01-01
            • 2010-11-05
            • 1970-01-01
            • 2012-06-24
            • 1970-01-01
            相关资源
            最近更新 更多