AngularJS:使用$ compile时,子指令中没有控制器

时间:2015-07-16 10:07:16

标签: angularjs

我的父指令带有一个包含有关网站结构信息的文件,并动态构建模板字符串。此字符串的内容引用其他指令。这些可以从源获取数据以构建(例如)表。

因为他们都使用$ http.get来获取数据,所以我想在使用所需控制器准备好这些子指令时通知父指令。

问题:父指令使用$ compile来构建站点,并且不“转发”控制器,导致“错误:[$ compile:ctreq] http://errors.angularjs.org/1.4.1/ $ compile / ctreq ...”< / p>

已经找到了这个答案:“Angular $compile with required controller”这不是一个很大的帮助,特别是因为transcludedControllers似乎已被弃用而且在我的代码中不起作用。

任何帮助或只是指向另一个已经问过/已回答的问题,我们非常感谢。

angular.module('TestDirectives', [])
.directive('widgetBlock', function ($compile) {
    return {
        restrict: 'A',
        replace: true,
        controller: function ($scope) {
            this.reportReady = function () {
                $scope.widgetready = String(Number($scope.widgetready) + 1);
            }
        },
        link: function (scope, elem, attr) {

            // template data will be constructed dynamically based on a 
            // xml - file fetched with $http.get
            var template = '<div><p >This isn\'t always fun</p>' +
                '<div mini-widget></div>' +
                '<div micro-widget></div></div>';

            var content = $compile(template)(scope)
            elem.append(content);


            attr.$observe('widgetready', function (newValue) {
                // quantity of widgets depends on widgets found in xml - file
                if (newValue === "2") {
                    // all widgets on screen, translate some keys
                    console.info("Application is ready to translate!!");
                }
            });
        }

    };
})
.directive('miniWidget', function ($compile, $http) {
return {
    restrict: 'A',
    require: '^widgetBlock',
    scope: {},
    link: function (scope, elem, attr, ctrl) {
        $http.get('json/daten.json').then(function (data) {
            scope.person = data.data;
            var test = '<p>hello {{person.name}}</p>';
            var content = $compile(test)(scope)
            elem.append(content);
            ctrl.reportReady();
        });
    }
}
})

.directive('microWidget', function ($compile, $http) {
return {
    restrict: 'A',
    require: '^widgetBlock',
    scope: {},
    link: function (scope, elem, attr, ctrl) {
        $http.get('json/daten2.json').then(function (data) {
            scope.person = data.data;
            var test = '<p>Whatever {{person.name}}</p>';
            var content = $compile(test)(scope)
            elem.append(content);
            ctrl.reportReady();
        });
    }
}
});

要完成,主要应用

angular.module('DirectiveTestApp', ['TestDirectives'])
.controller('MainController', function ($scope) {
    $scope.widgetready = "0";
});

和html

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Directives Test</title>
</head>
<body ng-app="DirectiveTestApp">
    <div ng-controller="MainController">
        <div widget-block widgetready="{{widgetready}}">

        </div>
    </div>
    <script src="bower_components/angular/angular.min.js"></script>
    <script src="script/app.js"></script>
    <script src="script/directives.js"></script>
</body>
</html>

非常感谢!

1 个答案:

答案 0 :(得分:0)

当您$compile然后link - 您正在使用$compile(template)(scope)时 - 在链接阶段,microWidget指令会查找所需的控制器DOM树。问题是你的模板当时不在DOM中。

有两种方法可以解决这个问题:

#1:使用cloneAttachFn

链接功能的第二个参数($compile(template)的结果)允许您指定cloneAttachFn - 请参阅documentation。此函数在链接阶段之前调用,并获取待链接节点的克隆版本。使用该函数将元素放在需要的位置:

var content = $compile(template)(scope, function cloneAttachFn(clonedContent){
  // this happens prior to link-phase of the content
  elem.append(clonedContent);
});

// this happens after link-phase of the content, so it doesn't work
// elem.append(content)

(顺便说一下,content[0] === clonedContent[0]

#2:追加$compile / link之前的内容(正如this question的回答中所建议的那样):

var content = angular.element(template);
elem.append(content);
$compile(content)(scope);

<强> Demo