2014-02-14 54 views
0

我需要使用AngularJS動態添加和初始化一組控制器。我能夠使用下面的代碼添加控制器(基於'UPDATE 2' of this answer),但不知道如何動態地將數據傳遞給控件。我的代碼如下,也可用JSFiddle。目標是在模板中添加{{ field_name }}{{ field_type }},現在它們都是空白的。我試圖設置這些使用ng-init,但似乎並不奏效。使用Angular動態加載控制器和控制器數據

這是我第一次使用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

這裏是你可以操縱的控制範圍的方式:

//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).

+0

是的,這就是我要完成的,謝謝。在我的JS結尾的''compile''調用之前,使用''rootScope''來做'Angularish'會是什麼?如果可能,我會非常感謝使用我的代碼的示例。 –

+0

@HakanB。我在答案中包含了一個簡單的現場演示。我不確定你的項目需要什麼 - 使用你的代碼對我來說可能是相當困難的。懶惰加載這樣的事情不是真正的「Angularish」,不管你做什麼,因爲開發者沒有記住它......這只是幸運的可能。無論你做什麼,只要按照通常的最佳做法。我認爲這裏唯一需要的是$編譯發生在一個指令中,因爲這是dom操作,另一個邏輯應該在一個服務中(比如獲取/創建控制器函數)。 – m59

+0

好的 - 非常感謝您的幫助。我不確定你是否看到過,但如果這有助於處理我的代碼,那麼我包含了一個JSFiddle:http://jsfiddle.net/hakanb/Fy94Y/否則,我會與你給我的東西一起工作。謝謝。 –