使用Angular动态加载控制器和控制器数据

时间:2014-02-14 00:16:26

标签: javascript angularjs

我需要使用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>

1 个答案:

答案 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).