我有一個指令,動態地加載一些AngularJS(v1.2.16)組件。它從WebAPI請求組件列表,然後加載它所告知的文件,最後使用$compile
編譯組件。
但是,組件在初始加載後會丟失$scope
!如果組件中有ng-click
事件,它將拒絕被解僱!
這是我的指導我的主要JS文件中:
var myApp = angular.module(.......);
myApp.directive('components', function($compile, $http) {
return {
restrict: 'A',
link: function (scope, element) {
$http.get('myapi/getListOfComponents').success(function(components) {
var scripts = Array();
var templates = Array();
angular.forEach(components, function (component, key) {
if (component.JavaScript !== null) {
// This is the path to the JS file to dynamically load
scripts.push(widget.JavaScript);
}
});
// Load the JS file for all the components
// I'm using the dynamic loader found here: https://github.com/ded/script.js (it's old, but it works)
$script(scripts, function() {
angular.forEach(widgets, function (widget, key) {
templates.push(
// Get the raw HTML contents of the component
$http.get(widget.Template).success(function (componentHtmlContent) {
element.append('<div class="component">' + componentHtmlContent + '</div>');
$compile(element.contents())(scope);
}));
});
});
});
}
}
});
和示例組件模板:
<div ng-controller="myComponentController">
<h2>{{MyHeading}} - {{MyInlineFunction()}} - {{SomeValue}}</h2>
<button ng-click="MyClickFunction()">Button</button>
</div>
和組件的腳本
serviceWebApp.controllerProvider('myComponentController', function ($scope, $http) {
$scope.SomeValue = "Foo";
$http.get('/myapi/getsomedata').success(function (data) {
$scope.MyHeading = data;
});
$scope.MyInlineFunction = function() {
return "SomeInlineValue";
}
$scope.MyClickFunction = function() {
alert('Something was clicked');
}
});
頁面加載時,調用MyInlineFunction
和$http.get
都很好,並且所有的綁定在模板({{MyHeading}} - {{MyInlineFunction()}} - {{SomeValue}}
)中獲取正確的值。
另一方面,該按鈕拒絕工作。 MyClickFunction
永遠不會被調用。
我也試着在瀏覽器開發者控制檯使用以下命令在該控制器的範圍的內容看:
angular.element($("div[ng-controller~='myComponentController']")).scope()
範圍返回從這個確實不包含SomeValue
,或範圍中定義的其他值/函數。
因此,$compile
似乎只工作一次,並沒有跟蹤範圍。
這是怎麼回事,我該如何解決?
的問題是,您對多個控制器在同一範圍內運行。他們可以互相覆蓋'MyClickFunction'或其他任何東西。它可能應該是'$ compile(element.contents())(scope。$ new())'。如果不是這種情況,請提供http://stackoverflow.com/help/mcve - 一個普通的會很好。 – estus
達尼特!我試圖創建一個plunkr來證明這一點,但我當然可以讓它在那裏工作!但是我看不出我的實際代碼有什麼問題,但我真的不想在此分享生產代碼。第二十二條軍規。 – GTHvidsten
我終於明白是什麼導致了這一點。動態添加後,我做了一些與使用jQuery的元素雜耍。這顯然與AngularJS的內部狀態不知所措,並導致組件失去與其範圍的連接。解決方案是在最底層執行'$ compile',在jQuery玩雜耍之後。現在我每次都會調用ng-click函數:)我將關閉這個問題,而不是刪除它,以供將來的訪問者使用。 – GTHvidsten