在 Angular 模板中引入外部 JS 小部件

10

我需要在我的AngularJS模板中包含一个脚本标签,以便渲染小部件。

例如,我会包含这个:

<script type="text/javascript" src="http://100widgets.com/js_data.php?id=106"></script>

但是 Angular 不会渲染它。


有任何控制台错误吗? - Vineet
没有错误,但什么也没有渲染。顺便说一句,我正在使用AngularJS v1.3.4。 - waney
你能提供更多的代码吗?Angular的代码在哪里?你想把这个脚本放在哪里,它的目的是什么? - aprok
如果我将此模板放入HTML文件(非Angular文件),它将被呈现,但如果您将上面的代码放在任何Angular视图中,它将不会呈现。 - waney
2个回答

2
由于100widgets脚本操作DOM并向HTML文件添加其他<script>标签,因此可能无法正常工作。此外,其中一些小部件是基于Flash的,因此脚本会添加对SWF对象的引用。我认为一种可能性是分析src属性中url的请求输出(在您的示例中为http://100widgets.com/js_data.php?id=106),并尝试将相应的DOM操作和脚本添加到您希望小部件出现的模板中。
以下是一个示例,显示了一个页面(page1)不起作用(只是按照您键入的方式添加了脚本标记),以及第二个页面(page2),其模板具有显示日历小部件所需的插入项。
注:由于沙箱限制,此片段在SO上可能无法工作;请尝试在调试模式下使用此CodePen版本:http://codepen.io/beaver71/pen/MyjBoP,或创建您自己部署在本地Web服务器上的版本。

(function() {
  'use strict';

  angular.
  module('myApp', ['ui.router']).
  config(configRouteProvider).
  controller('AppCtrl', AppCtrl);

  function AppCtrl($location, $rootScope) {
    $rootScope.$on('$stateChangeStart', onStateChangeStart);

    function onStateChangeStart(event, toState, toParams, fromState, fromParams, options) {
      console.log('From:', fromState.name,
        'to:', toState.name);
    }
  }

  function configRouteProvider($stateProvider, $urlRouterProvider) {
    $stateProvider
      .state('home', {
        url: '/',
        templateUrl: 'views/home.html'
      })
      .state('page1', {
        url: '/pag1',
        templateUrl: 'views/page1.html',
      })
      .state('page2', {
        url: '/pag2',
        templateUrl: 'views/page2.html',
      });
    $urlRouterProvider.otherwise('/');
  }

}());
body {
  margin: 0px;
}
hr {
  margin: 0px;
}
.tabs {
  padding: 8px;
  background-color: black;
  color: white;
}
.tabs a,
.tabs a:visited,
.tabs a:active,
.tabs a:hover {
  color: white;
}
.my-tab {
  height: 100%;
  width: 100%;
  position: absolute;
  padding: 8px;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <script src='//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
  <script src='https://code.angularjs.org/1.4.0/angular.min.js'></script>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.18/angular-ui-router.js'></script>
</head>

<body ng-app="myApp" ng-controller="AppCtrl as app">
  <div class="tabs">
    <a href="#" ui-sref="home">Home</a>
    <a href="#" ui-sref="page1">Page1</a>
    <a href="#" ui-sref="page2">Page2</a>
  </div>
  <hr />
  <div ui-view></div>

  <script id="views/home.html" type="text/ng-template">
    <div class="my-tab">
      <h3>Home</h3>
      <p>bla bla bla</p>
    </div>
  </script>

  <script id="views/page1.html" type="text/ng-template">
    <div class="my-tab">
      <h3>Page1</h3>
      <p>Using script type="text/javascript"... NOT WORKING:</p>
      <script type="text/javascript" src="http://100widgets.com/js_data.php?id=106"></script>
    </div>
  </script>

  <script id="views/page2.html" type="text/ng-template">
    <div class="my-tab">
      <h3>Page2</h3>
      <p>Workaround</p>
      <!--code1-->
      <div class="scriptcode">
        <!--ecode1-->
        <a target='_blank' href='http://100widgets.com/calendars/106-calendar.html'>
          <embed align="middle" id="calendar" width="170" height="156.111111111" allowscriptaccess="always" quality="high" salign="lt" wmode="transparent" src="http://100widgets.com/js-files/postit.swf?UTCoffset=0&amp;gid=0&amp;text1=St Valentines is on 14th February 2012&amp;&amp;event_time=&amp;rec=&amp;rnd=0&amp;gha=0&amp;ghb=0&amp;ghf=1&amp;gbc=FFB200&amp;gfc=040244&amp;gtc=F9F9FF&amp;gnu=http://mycalendar.org/widget/&amp;fna=&amp;ims="
          type="application/x-shockwave-flash" />
        </a>
        <!--code2-->
      </div>
      <!--ecode2-->
      <!--below commented cause it's not necessary -->
      <!--script type="text/javascript">
        var js = document.createElement("script");
        js.type = "text/javascript";
        js.src = "http://100widgets.com/stat.js.php";
        document.body.appendChild(js);
      </script-->
    </div>
  </script>
</body>


0
由于安全限制,Angular不会解析模板内的<script>标签。
那么你所提到的小部件正在利用document.write。一旦页面加载完成,document.write将不可用。
因此,在这里似乎没有简单的解决方法。

然而,正如您所尝试做的那样,这是在添加脚本中非常常见的事情,krux创建了postscribe。绕过此问题的方法。我创建了一个使用此库的小指令。

在您的模板中,它看起来像这样:

<div ps-src="http://100widgets.com/js_data.php?id=21"></div>

该指令:

  function psScr($document) {
    return {
      restrict: 'A',
      scope: {
        psSrc: '@'
      },
      link: link
    }

    function link(scope, elm) {
      if (typeof postscribe !== 'undefined') {
        postscribe(elm[0], `<script src='${scope.psSrc}'></script>`);
      } else {
        // If postscibe isn't loaded, first load the needed libarary
        var script = document.createElement('script');
        script.src = 'https://gitcdn.xyz/repo/krux/postscribe/master/dist/postscribe.js';
        script.onload = function () {
          // once postscibe is in, kick it into action.
          link(scope,elm); 
        };
        document.head.appendChild(script);
      }
    }
  }

  angular.module('psSrcModule', [])
    .directive('psSrc', psScr);

你可以在这个plunk中看到它的效果

然而,并不是所有的小部件都能与postscribe很好地配合使用,其中一些似乎在HTML中显示了一些瑕疵。我目前没有时间去找出是谁导致了这个问题(100widgets还是postscribe),但如果你真的需要这个功能,这是可以解决的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接