如何在 AngularJS 中绑定 <script> 元素的 src 属性

How to bind <script> element's src attribute in AngularJS

本文关键字:script 属性 src 元素 AngularJS 绑定      更新时间:2023-09-26

我正在尝试将 HTML <script> 元素的 src 属性绑定到角度控制器中的变量,以便我可以从控制器更新它而无需处理任何 UI。

到目前为止,我已经尝试了所有这些选项:

<script type="text/javascript" ng-src="{{sourceUrl}}"></script>
<script type="text/javascript" src="{{sourceUrl}}"></script>
<script type="text/javascript" ng-src="sourceUrl"></script>

在我的控制器中,我有:

$scope.sourceUrl = "https://<some url goes here>";

在设置$scope.sourceUrl后在浏览器中运行页面时,没有对sourceUrl的传出请求,所以我确定我做错了什么。有什么想法吗?

我找到了几篇关于<img>元素属性src帖子,ng-src应该按照他们所说的工作,但我想<script>有些不同。

不幸的是,你不能以这种方式使用 Angular。 Angular 仅在页面加载和构建后处理网页,此时<script>标签已被处理一次(脚本标签只运行一次)。 其他标签(例如 img)将在页面加载后其属性更改时更改屏幕的视觉外观......但如前所述,脚本只处理一次,即使在页面加载期间和 Angular 获得控制权之前。

您可以从控制器中将其动态添加到正文的末尾:

        $("<script>").attr({src: $scope.sourceUrl}).appendTo("body");
根据

@Jonathan的建议添加我的解决方案作为答案。

(function (ng) {
    // Retrieve main app module
    var appModule = angular.module('appModule');
    // This directive appends a child <script> element to an element with 'my-container' attribute.
    // This is needed for 'src' attribute generation and script evaluation of some object after the
    // page has been loaded.
    appModule.directive('myContainer', ['$log', 'MvcModelService', function ($log, MvcModelService) {
        return {
            restrict: 'A',
            scope: false,
            link: function (scope, elem, attrs) {
                var s = document.createElement("script");
                s.type = "text/javascript";
                var JSObjectName = "JSObject";
                // Just a random number ...
                var randomNumber = Math.floor(Math.random() * Number.MAX_VALUE);
                // flowId is a UUID representing current session.
                var flowId = MvcModelService.FlowId;
                // Construct the url  where the object contents will be loaded from:
                var Url = MvcModelService.UrlPrefix + "Get" + whatever + "/" + JSObjectName +
                          "someOtherStuffDepending on flowId and randomNumber";
                s.src = Url;
                $log.info("Adding script element to MyContainer with source url: " + Url);
                elem.append(s);
            }
        };
    }]);
}(angular));

视图代码段如下:

<div id="JSObjectScript" style="display: inline" my-container />

@Kolban是正确的,无论如何,您可以尝试创建脚本元素,添加 src attr,然后将其附加到模板中。例如:

 var exampleController = function() {
 controller.exampleController= [ '$sce',function($sce) {
     //Remember to set the src as a trusted src
     var trustedSrc = $sce.getTrustedUrl("www.example.com");
     var scriptElement = document.createElement('script');
     //Add attributes 
     scriptElement.setAttribute("data-size", '1220x700' );
     scriptElement.setAttribute("src", trustedSrc);

     //Append the srcipt to some element in the template
     var elementContainer = angular.element('#elementToAppend');
     elementContainer.append(scriptElement);
 }]
return controllers;
}

尽管脚本标签只能插值一次,但您可以添加更多脚本标签。

<script ng-repeat="script in scripts" ng-src="{{script.src}}"></script>

在您的控制器中,只需将更多对象(如{src: 'foo.js'})推送到脚本数组和 presto,延迟加载脚本。

这里有一个 Plunker 来演示这一点:http://plnkr.co/edit/6QuwuqsGoyrASk8FKmu2?p=preview

我知道

答案来得晚了,但这里有一个优雅而简单的解决方案:

您必须将脚本上下文转义与 $sce.trustAsResourceUrl(value) 一起使用。

请参阅文档

它可能看起来像:

在应用中.js:

//Dynamic Url for Tagging
    $rootScope.exUrl1 = $sce.trustAsResourceUrl(confserver.example.url);

在索引中.html:

<script type="text/javascript" src="{{exUrl1}}"></script>

脚本标记的 src 属性将绑定到其在 Angular 中的值。这是我运行我的 Web 应用程序并启动调试器以检查呈现的 HTML 时的结果:

<script type="text/javascript" src="http://exampleUrl.js"></script>

请注意,如果在第一次加载标签后完成绑定,则脚本将不会执行!

使用 AngularJS 指令的解决方案。

function dynamicScript () {
    return {
        restrict: 'E',
        scope: {
            dynamicScriptSrc: '='
        },
        link: function(scope, element, attrs, ngModel) {
            setScriptSrc(element, scope.$eval(attrs.dynamicScriptSrc));
            scope.$watch('dynamicScriptSrc', src => {
                setScriptSrc(element, src);
            });
        }
    }
}
function setScriptSrc(element, src) {
    if(src) {
        var newScript = document.createElement("script");
        newScript.type = 'text/javascript';
        newScript.src = src;
        element.empty();
        element.append(newScript);
    }
}

用法:

<dynamic-script dynamic-script-src="vm.dynamicJsPath"></dynamic-script>