我有一个现有的页面,我需要把一个Angular 的应用程序与控制器,可以动态加载。
下面是一个代码片段,它实现了我根据API和我发现的一些相关问题所做的最佳猜测:
// Make module Foo
angular.module('Foo', []);
// Bootstrap Foo
var injector = angular.bootstrap($('body'), ['Foo']);
// Make controller Ctrl in module Foo
angular.module('Foo').controller('Ctrl', function() { });
// Load an element that uses controller Ctrl
var ctrl = $('<div ng-controller="Ctrl">').appendTo('body');
// compile the new element
injector.invoke(function($compile, $rootScope) {
// the linker here throws the exception
$compile(ctrl)($rootScope);
});
JSFiddle。注意,这是实际事件链的简化,在上面的行之间存在各种异步调用和用户输入。
当我尝试运行上面的代码时,$compile返回的链接器抛出:Argument 'Ctrl' is not a function, got undefined
。如果我对bootstrap的理解正确,它返回的injector应该知道Foo
模块,对吗?
如果我使用angular.injector(['ng', 'Foo'])
创建一个新的注入器,它似乎可以工作,但它创建了一个新的$rootScope
,它不再是Foo
模块被引导的元素的作用域。
我使用了正确的功能吗?还是我遗漏了什么?我知道这不是Angular的方式,但我需要向不使用Angular的旧页面添加新组件,而且我不知道引导模块时可能需要的所有组件。
更新日期:
我已经更新了fiddle,以显示我需要能够在不确定的时间点向页面添加多个控制器。
8条答案
按热度按时间iyzzxitl1#
我发现了一个可能的解决方案,在引导之前我不需要知道控制器:
Fiddle。唯一的问题是,您需要存储
$controllerProvider
,并在不应该使用它的地方使用它(在引导程序之后)。此外,似乎没有一种简单的方法来获得用于定义控制器的函数,直到它被注册,所以我需要循环通过模块的_invokeQueue
,这是未记录的。**UPDATE:**要注册指令和服务,只需分别使用
$compileProvider.directive
和$provide.factory
,而不是$controllerProvider.register
。同样,您需要在初始模块配置中保存对这些指令和服务的引用。UDPATE 2:Here's a fiddle会自动登录所有载入的控制器/指示词/服务,而不需要个别指定。
guykilcj2#
bootstrap()将为您调用AngularJS编译器,就像ng-app一样。
Fiddle。
g6baxovj3#
我建议看一下ocLazyLoad library,它在运行时注册模块(或现有模块上的控制器、服务等),并使用requireJs或其他类似的库加载它们。
p4tfgftt4#
我还需要添加多个视图,并在运行时从angularJs上下文之外的javascript函数将它们绑定到控制器,因此我得到了以下结果:
现在,调用setCnt()函数将注入并编译html,并将其链接到第二个控制器:
下面是一个测试示例:https://refork.codicode.com/x4bc
希望这对你有帮助。
nx7onnlm5#
我刚刚改进了Jussi-Kosunen编写的函数,这样所有的事情都可以通过一个调用来完成。
通过这种方式,您可以从任何地方加载模板,并以编程方式示例化控制器,甚至是嵌套控制器。
下面是一个将一个控制器加载到另一个控制器中的工作示例:http://plnkr.co/edit/x3G38bi7iqtXKSDE09pN
q8l4jmvw6#
为什么不使用config和ui-router?
它是在运行时加载的,您不需要在html代码中显示控制器
例如类似以下内容
xwbd5t1u7#
这是我所做的,实际上是2部分,使用ng-controller及其范围定义函数,然后$controller服务来创建动态控制器:-
首先,HTML -我们需要一个静态控制器,它将示例化一个动态控制器。
静态控制器“staticCtrl”定义了一个名为“dynamicCtrl”的作用域成员,调用该成员可创建动态控制器。ng-controller将按名称获取预定义的控制器,或在当前作用域中查找同名函数。
我们使用eval()来获取字符串(我们的动态代码可以来自任何地方),然后$controller服务将获取预定义的控制器名称(正常情况下)或函数构造函数后跟构造函数参数(我们传入一个新的作用域)- Angular将注入(像任何控制器一样)到函数中,我们只请求上面的$scope和$rootScope。
kmb7vmvb8#
上面的代码只是一个示例。
这样就不需要在页面上的任何地方放置
ng-controller="someController"
-只需声明<body ng-app="mainApp">
相同的结构可用于每个模块或模块内的模块