我需要使用AngularJS动态添加和初始化一组控制器。我能够使用下面的代码添加控制器(基于'UPDATE 2' of this answer),但不了解如何动态地将数据传递给控件。
我的代码位于下方,也可以JSFiddle的形式提供。目标是在添加模板后填充{{ field_name }}
和{{ field_type }}
- 现在它们是空白的。我尝试使用ng-init
设置这些但这似乎不起作用。
这是我第一次使用AngularJS而且我来自Backbone背景,所以我道歉我错过了一些明显的东西,请感觉纠正任何事情。从客户端上定义的动态数据结构添加和初始化控制器是项目的要求,因此我将无法在服务器上呈现页面内容或进行其他API调用。提前谢谢。
使用Javascript:
DATA_FIELDS = [
{'field_name': 'name', 'field_type': 'str'},
{'field_name': 'location', 'field_type': 'str'},
{'field_name': 'is_active', 'field_type': 'bool'}
]
// Create base module and store providers for later use
providers = {};
editorApp = angular.module('editorApp', [],
function ($controllerProvider, $compileProvider, $provide) {
providers = {
$controllerProvider: $controllerProvider,
$compileProvider: $compileProvider,
$provide: $provide
};
}
);
// Boostrap base module
angular.bootstrap($('body'), ['editorApp']);
// Store our _invokeQueue length before loading our controllers
// This is just so we don't re-register anything
queueLen = angular.module('editorApp')._invokeQueue.length;
// Define controller for string field
angular.module('editorApp').controller('DisplayFieldStr',
function ($scope, $rootScope) {
}
);
// Define controller for boolean field
angular.module('editorApp').controller('DisplayFieldBool',
function ($scope, $rootScope) {
}
);
// Register the controls/directives/services we just loaded
var queue = angular.module('editorApp')._invokeQueue;
for(i=queueLen;i<queue.length;i++) {
var call = queue[i];
// call is in the form [providerName, providerFunc, providerArguments]
var provider = providers[call[0]];
if (provider) {
provider[call[1]].apply(provider, call[2]);
}
}
// Append templates to content div and set init attrs
for (i = 0; i < DATA_FIELDS.length; i += 1) {
field = DATA_FIELDS[i];
init_data = 'field_name=\''+field.field_name+'\', ';
init_data += 'field_type=\''+field.field_type+'\'';
div = $('.templates .df-' + field.field_type).clone().appendTo('.content');
div.attr('id', 'df-' + field.field_name);
controller_name = 'DisplayField' + field.field_type[0].toUpperCase() + field.field_type.substring(1);
div.attr('ng-controller', controller_name);
div.attr('ng-init', init_data);
}
// compile the new element
$('body').injector().invoke(function ($compile, $rootScope) {
for (i = 0; i < DATA_FIELDS.length; i += 1) {
field = DATA_FIELDS[i];
$compile($('#df-' + field.field_name))($rootScope);
}
$rootScope.$apply();
});
HTML:
<div class='content'></div>
<div class='templates' style='display: none;'>
<div class='df df-str'>
<ul>
<li>Template: df-str</li>
<li>Field name: {{ field_name }}</li>
<li>Field type: {{ field_type }}</li>
</ul>
</div>
<div class='df df-bool'>
<ul>
<li>Template: df-bool</li>
<li>Field name: {{ field_name }}</li>
<li>Field type: {{ field_type }}</li>
</ul>
</div>
</div>
答案 0 :(得分:1)
这是一种可以操纵控制器范围的方法:
//create a new scope from an existing one
var newScope = scope.$new();
//add whatever data you want to
newScope.someProperty = 'some value';
//compile the html with your custom scope
$compile(element.contents())(newScope);
假设编译的html看起来像这样:
<p>{{someProperty}}</p>
结果将是:
<p>some value</p>
<强> Live demo (click). 强>