我有一个现有页面,需要在其中添加一个可以动态加载的控制器的角度应用程序。
这是一个片段,它根据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
。如果我正确地理解了引导程序,那么它返回的注射器应该知道该Foo
模块,对吗?
相反,如果我使用制作了一个新的注入器angular.injector(['ng', 'Foo'])
,它似乎可以工作,但是会创建一个新的注入器,该注入器$rootScope
的范围不再与Foo
引导该模块的元素相同。
我是在使用正确的功能来执行此操作还是错过了某些功能?我知道这不是Angular的方法,但是我需要在不使用Angular的旧页面中添加使用Angular的新组件,而且我不知道引导模块时可能需要的所有组件。
更新:
我已经更新了小提琴,以表明我需要能够在不确定的时间点向页面添加多个控制器。
我找到了一种可能的解决方案,在引导时无需了解控制器:
// Make module Foo and store $controllerProvider in a global
var controllerProvider = null;
angular.module('Foo', [], function($controllerProvider) {
controllerProvider = $controllerProvider;
});
// Bootstrap Foo
angular.bootstrap($('body'), ['Foo']);
// .. time passes ..
// Load javascript file with Ctrl controller
angular.module('Foo').controller('Ctrl', function($scope, $rootScope) {
$scope.msg = "It works! rootScope is " + $rootScope.$id +
", should be " + $('body').scope().$id;
});
// Load html file with content that uses Ctrl controller
$('<div id="ctrl" ng-controller="Ctrl" ng-bind="msg">').appendTo('body');
// Register Ctrl controller manually
// If you can reference the controller function directly, just run:
// $controllerProvider.register(controllerName, controllerFunction);
// Note: I haven't found a way to get $controllerProvider at this stage
// so I keep a reference from when I ran my module config
function registerController(moduleName, controllerName) {
// Here I cannot get the controller function directly so I
// need to loop through the module's _invokeQueue to get it
var queue = angular.module(moduleName)._invokeQueue;
for(var i=0;i<queue.length;i++) {
var call = queue[i];
if(call[0] == "$controllerProvider" &&
call[1] == "register" &&
call[2][0] == controllerName) {
controllerProvider.register(controllerName, call[2][1]);
}
}
}
registerController("Foo", "Ctrl");
// compile the new element
$('body').injector().invoke(function($compile, $rootScope) {
$compile($('#ctrl'))($rootScope);
$rootScope.$apply();
});
小提琴。唯一的问题是,您需要存储,$controllerProvider
并在确实不应该使用它的地方(在引导程序之后)使用它。同样,在注册之前,似乎还没有一种简单的方法来获得用于定义控制器的函数,因此我需要遍历模块_invokeQueue
中未记录的。
更新:
注册指令和服务,而不是分别$controllerProvider.register
简单地使用$compileProvider.directive
和$provide.factory
。同样,您需要在初始模块配置中保存对这些引用的引用。
UDPATE 2:
这是一个小提琴,可以自动注册所有加载的控制器/指令/服务,而无需单独指定它们。
问题内容: 我目前有一个内置路由的AngularJS应用,它与静态属性分配完美配合。但是我真正想做的是为控制器分配不同的路由: 我想做的是在这里对我的财产做同样的事情,例如: 但似乎我得到一个错误,说找不到 所以有什么办法可以在路由配置中动态加载控制器功能名称? 问题答案: 使用angular ui-router可以做到这一点。 ui-router允许您指定“ controllerProvider
问题内容: 看来这个问题已经被问过几次了,但是没有正确的答案。 我的情况:我正在使用ajax(出于某种原因不使用角度路由模板)将模板(带有html和脚本)初始化为div。 index.html(主要) template.html(模板) 当我单击按钮时,它将文件加载到容器中,但是出现错误 错误:[ ng:areq ]参数’TempCtrl’不是函数,未定义 尽管已将其添加到应用控制器中。 我如何动
问题内容: 是否可以基于路由组动态加载控制器,js文件和模板?伪代码不起作用: 我已经看到了很多这样的问题,但是没有一个问题基于路由组加载js文件/控制器。 问题答案: 我设法解决了受@ calebboyd,http : //ify.io/lazy-loading-in-angularjs/ 和http://weblogs.asp.net/dwahlin/archive/2013/05/22/dy
问题内容: 在这种简化的情况下,我有两个文件:index.htm,lazy.htm。 index.htm: 懒汉 结果是一个错误:“参数’lazy’不是一个函数,未定义” 改用函数 懒汉 直到1.3版本beta 14才可以使用。在beta 15中,删除了全局控制器功能:https : //github.com/angular/angular.js/issues/8296 因此,现在,有什么更好的方
问题内容: 我刚开始使用angularJS,并努力为我要做的事情找出合适的架构。我只有一个页面应用程序,但 URL始终应该保持不变 ;我不希望用户能够导航到根以外的任何路由。在我的应用中,有一个主要的div需要承载不同的视图。访问新视图时,我希望它接管主div中的显示。以这种方式加载的视图可以被丢弃或停留在DOM中,就像隐藏在DOM中一样- 我很想知道每个视图如何工作。 我提出了一个我想做的粗略的
问题内容: 我正在尝试为包含的模板动态分配控制器,如下所示: 但是Angular抱怨这是不确定的。 我猜,是不是定义 尚未 (因为我可以附和了在模板中)。 我见过很多关于人们设置等于变量的示例,例如:。但是,如果不创建重复的并发循环,就无法弄清楚在需要时如何获得可用值。 PS我也尝试在模板中进行设置(认为到那时它一定已经解决了),但是没有骰子。 问题答案: 您的问题是ng-controller