AngularJS指令范围和$ compile - 变量返回空白

时间:2013-10-18 00:59:51

标签: javascript angularjs

有一点角度的问题,我无法弄清楚。我怀疑它可能与范围有关,但我不完全是100%。

这是我的HTML:

<i class="icon-question-sign" popover data-placement="top" data-trigger="hover" data-title="Top 10 clients" data-content-compile="<ul><li ng-repeat='client in user.clients | limitTo: 10'>{{client}}</li></ul>"></i>

这是我的指示:

app.directive('popover', function($timeout, $compile) {
var linker = function (scope, element, attrs) {
    $timeout(function() {
        var content = $compile(element.data('content-compile'))(scope);
        element.popover({
            'html': true,
            'content': content
        });
    }, 200);
}

return {
    restrict: 'A',
    link: linker
}

});

结果正确地将li重复到{{user.clients}}的正确长度,但不呈现{{client}}。出于某种原因,它是空白的,然而,它有一个字符串值,并且在直接添加到HTML而不是通过指令编译时起作用。它目前在DOM中的表现如何:

<ul class="ng-scope"><!-- ngRepeat: client in user.clients | limitTo: 10 --><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li></ul>

如果我用{{user.email}}替换{{client}},则会正确列出。

不确定这里有什么 - 我可能错过了一些明显的东西!

2 个答案:

答案 0 :(得分:2)

问题的关键是它的原因:数据内容编译中的{{client}}在指令启动之前被编译,因此在控制器上下文中将client未定义。目前,您发送到$ compile的字符串是:

<ul><li ng-repeat='client in user.clients | limitTo: 10'></li></ul>

为了防止这种情况,必须以其他方式将模板发送到指令中。以下是一些:

  1. 将模板作为字符串存储在控制器中。在我看来,相当丑陋。
  2. 将模板存储在模板中并从$ templateCache中检索。
  3. 我做了an example using second approach

    <div ng-controller="ctrl">
        <script type="text/ng-template" id="client.html">
            <div><ul><li ng-repeat='client in user.clients'>{{client.name}}</li></ul></div>
        </script>
        <i
            popover
            class="glyphicon glyphicon-user"
            data-placement="bottom"
            data-trigger="hover"
            data-title="Top 10 clients"
            data-content-template="client.html"
        ></i>
    </div>
    
    angular.module("app", [])
    .controller("ctrl", function($scope, User) {
        $scope.user = User;
    })
    .directive("popover", function($compile, $timeout, $templateCache) {
        return function(scope, el, attr) {
            $timeout(function() {
                el
                .popover({
                    html: true,
                    content: $compile($templateCache.get(attr.contentTemplate))(scope)
                })
                .popover("show")
            });    
        };
    })
    .value("User", {
        clients: [
            { name: "John", age: 22},
            { name: "Ann", age: 13},
            { name: "Maria", age: 62},
            { name: "Ivan", age: 44}
        ]
    });
    

答案 1 :(得分:0)

似乎答案比我预期的更直接,将我的指令改为:

// popover
app.directive('popover', function($timeout, $compile) {
    var linker = function (scope, element, attrs) {
        var content = $compile(element.data('content-compile'))(scope);
        $timeout(function() {
            element.popover({
                'html': true,
                'content': content
            });
        }, 400);
    }

    return {
        restrict: 'A',
        link: linker
    }

});

唯一的区别是我将$ timeout周期加倍,并将编译后的变量移到了它之外。确保数据在被调用之前被编译。

不是100%确定这是否是正确的方法,但正在测试它在所有帐户上正确返回。虽然,如果你有类似的问题 - 用一小撮盐来解决这个问题。