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

AngularJS directive scope and $compile - variable returning blank

本文关键字:返回 空白 变量 compile 指令 范围 AngularJS      更新时间:2023-09-26

有一个我无法弄清楚的角度问题。我怀疑这可能与范围有关,但我不是 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}},它会正确列出。

不知道这里发生了什么 - 我可能错过了一些明显的东西!

问题

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

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

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

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

我使用第二种方法做了一个例子:

<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}
    ]
});

似乎答案比我预期的要简单一些,将我的指令更改为:

// 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% 确定这是否是正确的方法,但正在测试它在所有帐户上正确返回。虽然,如果您有类似的问题 - 请加一点盐。