AngularJS动态添加到页面

时间:2019-05-20 13:00:36

标签: html angularjs

我们在电子浏览器中有此AngularJS SP应用程序(智能镜像),该应用程序具有用户可创建的扩展。

扩展名是使用角度指令的html小片段 并使用控制器和服务。

要安装扩展程序,必须编辑主页并为控制器和服务功能插入脚本标签,为HTML代码段插入<div ng-include= ...>

硬编码此单页应用程序效果很好。

但是我想向此应用程序(开源)添加功能以某种方式动态加载这些元素...

将标签添加到dom的工作原理,但未正确处理。 在运行脚本(来自插入的标签)之前处理HTML,并且当ng-include插入HTML代码段时,尚未定义控制器...

主体(带有在硬编码位置的扩展名被注释掉)

    <body ng-controller="MirrorCtrl" ng-cloak> 
          <div class="top">
            <div class="top-left">
            <!--  <div ng-include="'plugins/datetime/index.html'"></div>
              <div ng-include="'plugins/calendar/index.html'"></div> -->
            </div>
            <div class="top-right">
            <!--  <div ng-include="'plugins/weather/index.html'"></div>
              <div ng-include="'plugins/traffic/index.html'"></div>
              <div ng-include="'plugins/stock/index.html'"></div>
              <div ng-include="'plugins/tvshows/index.html'"></div>
              <div ng-include="'plugins/ha-display/index.html'"></div> -->
            </div>
          </div>
    ...
    ...
    <script src="filename.service"/>
    <script src= filename.controller"/>
</body>

日历扩展html(插入页面的特定div区域)

<ul ng-controller="Calendar" class="calendar fade" ng-show="focus == 'default'" ng-class="config.calendar.showCalendarNames ? 'show-calendar-names' : ''">
    <li class="event" ng-repeat="event in calendar" ng-class="(calendar[$index - 1].label != event.label) ? 'day-marker' : ''">
        <div class="event-details">
            <span class="day">
                      <span ng-bind="event.startName"></span>
            <span ng-if="event.startName != event.endName"> - <span ng-bind="event.endName"></span></span>
            </span>
            <div class="details calendar-name" ng-bind="event.calendarName"></div>
            <span class="summary" ng-bind="event.SUMMARY"></span>
            <div class="details" ng-if="event.start.format('LT') != event.end.format('LT')">
                <span ng-if="event.startName != event.endName"><span ng-bind="event.start.format('M/D')"></span> <span ng-bind="event.start.format('LT')"></span>                - <span ng-bind="event.end.format('M/D')"></span> <span ng-bind="event.end.format('LT')"></span></span>
                <span ng-if="event.startName == event.endName"><span ng-bind="event.start.format('LT')"></span> - <span ng-bind="event.end.format('LT')"></span></span>
            </div>
            <div class="details" ng-if="event.start.format('LT') == event.end.format('LT')">All day</div>
        </div>
    </li>
</ul>

日历扩展程序控制器(由html使用)

function Calendar($scope, $http, $interval, CalendarService) {

    var getCalendar = function(){
        CalendarService.getCalendarEvents().then(function () {
            $scope.calendar = CalendarService.getFutureEvents();
        }, function (error) {
            console.log(error);
        });
    }

    getCalendar();
    $interval(getCalendar, config.calendar.refreshInterval * 60000 || 1800000)
}
console.log("registering calendar controller")
angular.module('SmartMirror')
    .controller('Calendar', Calendar);

日历扩展服务(由控制器使用,在此讨论中已缩短)

(function () {
    'use strict';

    function CalendarService($window, $http, $q) {
  ...
  ...
        return service;
    }
console.log("registering calendar service")
    angular.module('SmartMirror')
    .factory('CalendarService', CalendarService);

} ());

,因此想要添加扩展名的用户必须创建这些文件, 并编辑主页HTML并将其插入

<div ng-include src="filename.html"></div>

在正确的位置,然后添加

<script src="filename.service" >

<script src="filename.controller">

在正确的位置和顺序上,需要在控制器之前完成服务, 控制器使用服务。

无论如何,添加代码很容易找到所有扩展并将元素动态地插入dom各自的位置...但是...

在硬编码中,脚本被添加到正文中的html之后

因此,我添加了一个新脚本(在加载页面时进行处理),该脚本查找并插入所有元素以在正确的位置支持扩展。

,然后脚本结束....(硬编码HTML中的最后一个),并且处理了HTML指令,并且没有加载或处理动态添加的脚本,因此找不到控制器。

我可以创建一个包含所有这些信息的临时HTML文件,然后加载THAT而不是动态加载,但是我认为解决此问题更好

我尝试创建自己的角度指令并将其编译,但是陷入循环

<divinc src="filename.service"></divinc>

作为divinc指令的子代,插入的div是正确的

angular.module('SmartMirror')
.directive("divincl", ["$compile" ,function($compile){
      return {
        priority: 100, 
        terminal: true,
        compile: function(scope, element, attrs) {
                var html =  "<div ng-include=\"" + element['incl']+ "\" onload='function(){console.log(\'html loaded\')}'></div>"

                var templateGoesHere = angular.element(document.getElementById(element['id']));
                templateGoesHere.html(html);
                //document.body.innerHTML='';
               var v= $compile(templateGoesHere);
                //scope.$apply();
              return function linkFn(scope) {
                 v(scope) // Link compiled element to scope
              }
        }
      }
}]);

有关如何解决此问题的建议。谢谢

1 个答案:

答案 0 :(得分:0)

为了使angularjs 1.7应用程序能够动态加载扩展,有两种方法:

  • 两者都使用“嵌套的angularjs应用程序”,这显然是angularjs的高级用法,将需要您在2个angularjs应用程序之间进行通信,以使用$ scope。$ apply告诉其他应用程序进行更新等。
  • 要么不会在前端动态加载它们,而是在生成包含应用程序的html页面时在后端动态加载它们。尝试从头开始列出所有扩展名。

我建议您也不要忘记使用ng-include,并尝试在应用程序的指令中添加<script></script>

首先,您需要重新了解如何启动angularjs应用程序。

  • 加载主应用程序时,您有一个脚本,其中有angular.moduleangular.directiveangular.valueangular.configangular.run ...调用制作。这是声明步骤
  • 如果您声明一个模块MyApp,并且在html中有一个带有ng-app="MyApp"的DOM元素,则angularjs将在此DOM元素上自动运行angular.bootstrap()以便启动{{1 }}。应用程序的MyApp从此处开始。您无法在模块execution中声明任何内容。

其次,我认为模板中的MyApp代码已被清理并按角度删除。另外,即使您执行了代码,由于<script></script>已经完成,因此您不应该创建新的指令或注册新的服务,否则它将不起作用。

一个好方法是,当您加载插件时,您将:

  • 从头开始加载插件的脚本,它必须声明一个新的模块,例如declaration step
  • 在将包含插件的指令中,放入我发送给您的链接的代码,这可以插入子应用程序。最终,您的指令模板中将有一个MyPlugin1
  • 然后在该节点上调用<div ng-app="MyPlugin1"></div>,这将使启动子应用程序成为可能。

如果执行此操作,则可以运行子应用程序,但未传递参数。为了传递参数,您可以将模块angular.bootstrap的代码放入函数中,以建立应用程序工厂。然后使用MyPlugin1初始化应用。

例如:

app.value('param1', parameter1)

在指令调用function declarePlugin1(myParam1, myParam2) { var app = angular.module('MyPlugin1', []); // app.directive(); app.value('myParam1', myParam1); app.value('myParam2', myParam2); } 中,它将使用初始化值声明应用程序declarePlugin1("test", 42);,然后MyPlugin1告诉angularjs启动此应用程序。

您也可以传递回调,以便在两个应用程序之间进行通信。