我一直致力于一个更像框架的项目,并且有几个可以安装的应用程序/模块。将其视为基本appstore或google.play商店。它是一种Intranet应用程序,所有模块都可以添加到您的useraccount中。
该框架已经在开发中,但我现在正在围绕应用程序/模块的想法。 (link to a proof of concept in development, can be found here)
应用程序应该是独立的,并且不能突然包含来自框架的脚本。通过在单独的模块中构造它们是完全可能的:
angular.module('myApp', []);
然而,一个应用程序可以有模板,脚本,CSS,它可以在一个单独的服务器上运行,所以我有点寻找获取脚本和cssfile并动态加载它们的最佳方法当用户从框架内启动app
时,进入应用程序。
www.framework.com/apps/myapp/views/app.html
,为了简单起见,我将脚本捆绑到每个应用程序的1个脚本文件中,因此还有一个www.framework.com/apps/myapp/script.js
到包括在内。框架包含加载应用的模板和appController
。模板包含这一部分:
<div data-ng-controller="AppController" data-ng-include="app.appTemplate">
<div>loading...</div>
</div>
这基本上与加载所有脚本时更新的$scope.app.appTemplate
绑定,因此首先显示加载模板,稍后在页面中包含脚本后,它会将app.appTemplate
更新为上面提到的应用程序的主要模板。
在加载第一个索引模板时,此模板当前从框架加载AppController
,因此它使用框架的$scope
而不是它自己的脚本。
我仍然需要以某种方式启动应用程序自己的角度模块,并让它自己运行而不在框架中运行任何东西以“让它工作”
我还在搞清楚如何最好地加载依赖的javascript文件(可能会使用requrejs或其他依赖加载器)但我目前还不知道如何在没有在框架{{1}内工作的情况下“启动”应用程序}
修改
我创建了一个小型的演示项目,以显示手头的问题,full code is visible at git-hub此刻这个项目做了一些硬编码的事情,我的想法是当我得到证明概念是正确的,现在它是关于在框架内加载应用程序。如果可能的话,我可以考虑从哪里获取URL和应用程序名称......
答案 0 :(得分:37)
您无法在另一个引导模块内引导模块。 Bootstrapping编译视图并将rootScope绑定到它,遍历DOM并设置范围绑定并执行指令链接功能。如果你这样做两次,你就会遇到问题。
您可能不得不重新考虑您的架构。我认为可能与Angular有关的“模块”或“app”这个词是用词不当,并且正在引导你走错路。
应用程序中的每个“用户安装的应用程序”应该可能真的由应用程序模块中的控制器控制,或者注册到应用程序模块引用的模块。因此,您不会“启动多个应用程序”,您只需要启动一个,引用其他模块,然后使用这些模块中的控制器来控制屏幕上的部分视图。
你要做的是当安装一个新的“小部件”时,你将它的模块文件(.js)注册到系统,该系统将包含一个名为WidgetCtrl的控制器,然后当你的页面加载时,你会在您的应用模块上引用小部件的模块。从那里,它应该可以使用ng-controller和/或ng-include动态分配到元素。
我希望这是有道理的。
答案 1 :(得分:26)
与目前接受的答案相反,实际上是可能的。
我正在研究一个类似的问题,并建议我的答案是不可接受的。我以前写过多个应用程序的页面,但是几年前,应用程序彼此独立。基本上有两件事要做:
有一个ng-non-bindable属性,只是告诉AngularJS忽略该元素。这解决了我们的第一个问题。
但是当你尝试引导子元素时; AngularJS会抛出一个错误,告诉你它已经被引导(至少对我来说,版本1.2.13)。以下技巧完成了这项工作:
<div ng-non-bindable data-$injector="">
<div id="bootstrap-me">
<script src="/path/to/app.js"></script>
<div ng-include="'/path/to/app.html'"/>
</div>
</div>
这个解决方案并不完美。理想情况下,ng-non-bindable属性可以向元素添加所需的data- $ injector属性。我将创建一个功能,并希望对AngularJS提出拉取请求。
我没有机会提出拉取请求。显然和预期我应该说,一些内部组件已经改变,但ng-non-bindable仍在使用Ventzy Kunev的演示代码在1.3.13版本工作(再次感谢,请参阅下面的链接)。
答案 2 :(得分:4)
如果每个子应用程序都在自己的模块中,您可以使用angular.bootstrap动态加载该模块。当加载特定应用程序的URL时,您可以获取必要的脚本,然后当promise解析时,您可以执行以下操作:
// grab a reference to the element where you'll be loading the sub-app
var subapp = document.getElementById('subapp-id');
// assuming the script you get back contains an angular module declaration named
// 'subapp', manually start the sub-app
angular.bootstrap(angular.element(subapp), ['subapp']);
希望这会有所帮助
答案 3 :(得分:3)
与上面的UnicodeSnowman的答案类似,另一个看起来符合我需求的潜在解决方案(我在文档站点上构建了一个实时的Angular编辑器)是通过{{1}来手动处理引导过程。 }与主<div id="demos">
分开。
This article对于让它正常工作非常有帮助。
一般流程
<div id="myApp">
来完成此部分)ng-app
代码示例 (未经过测试;只显示基本流程)
someCoolDemoContainer
答案 4 :(得分:2)
我知道现在这已经很老了,但是我正在寻找一种方法在Angular应用程序中嵌入一个AngularJS应用程序并使用这篇文章的答案来做到这一点所以我想我会在这里发布一下plunker寻找类似解决方案的其他人。
我发现有两种方法可以做到这一点,它们都是在Angular组件的ngOnInit中使用angularjs app的手动自举:
ngOnInit(): void {
// manually bootstrap the angularjs app
angular.bootstrap(document.getElementById('ngListApp'), ['list-app']);
}
在要引导的元素上设置ngNonBindable属性:
<div ngNonBindable #insert>
<!-- can insert the angular js template directly here, inside non-bindable element -->
<div id="ngListApp" ng-controller="ListController as list">
<input ng-model="inputValue" />
<ul>
<li ng-repeat="item in items">{{ item }}</li>
</ul>
</div>
</div>
或者将angularjs模板html注入到Angular组件中的ngOnInit事件处理程序中的元素中,以便Angular在编译期间不会尝试解释AngularJS代码(尤其是使用大括号插入DOM中的AngularJS属性)
ngOnInit(): void{
// insert angularjs template html here
this.div.nativeElement.innerHTML = this.htmlTemplate;
// then manually bootstrap the angularjs app
angular.bootstrap(document.getElementById('ngListApp'), ['list-app']);
}
Plunker在这里: