带有$ compile的AngularJS组件会丢失$ scope

时间:2017-04-07 13:53:48

标签: javascript angularjs

我有一个动态加载一些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只能工作一次,而且无法跟踪范围。

这里发生了什么,我该如何解决?

1 个答案:

答案 0 :(得分:0)

这里的问题是我还使用jQuery来移动DOM中的元素。当我移动先前已初始化的组件时,它将失去与范围的连接。

我在调试时注意到的另一件事是First组件初始化三次,第二次组件初始化,第三次组件初始化。 (或&#34; 4,3,2,1和#34;如果有四个组成部分)。这是因为$compile(element.contents())(scope);位于foreach内,并且每个后续组件都会多次加载。

解决方案是将重新编译移动到所有jQuery之下,同时将其移动到所有HTML内容都已承诺加载时运行的块中。

在这里可以看到一个工作的Plunker:http://plnkr.co/edit/ZGnGXb9N3SsoIUjJx5N4?p=preview