AngularJS不编译具有ng-repeat的元素

时间:2015-01-12 16:06:21

标签: javascript angularjs

我创建了一个属性指令,用于替换使用它的元素内部的内容和加载图标,直到作为属性值的变量被评估为未定义的以外的其他内容。该指令的代码是:

  .directive('ngLoading', function (Session, $compile) {

      var loadingSpinner = '<div class="spinner">' + 
        '<div class="rect1"></div>' + 
        '<div class="rect2"></div>' +
        '<div class="rect3"></div>' +
        '<div class="rect4"></div>' +
        '<div class="rect5"></div></div>';

      return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        var originalContent = element.html();
        element.html(loadingSpinner);
        scope.$watch(attrs.ngLoading, function (val) {
            if(val) {
                element.html(originalContent);
                    $compile(element.contents())(scope);
            } else {
                element.html(loadingSpinner);
            }
        });
      }
    };
  });

我在以下方式中使用此指令:

<div ng-loading="user">
    {{user.name}}
</div>

这个div的内容被一个laoding图标取代,直到作用域变量用户包含一些数据,此时div的原始内容被放回div中,div由$ compile编译。

这在大多数情况下都可以正常工作,但当div的原始内容在某处有一个ng-repeat指令时它不起作用。以下情况不起作用,例如:

<div ng-loading="users">
    <table>
        <thead>
            <tr>
                <th>Name</th>
                <th>Age</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="user in users">
                <td>{{user.name}}</td>
                <td>{{user.age}}</td>
            </tr>
        </tbody>
    </table>
</div>

表被渲染但是tbody中没有渲染tr,就好像范围变量users是null一样。当我调试代码时,我可以看到变量用户的值确实是一个用户数组,就在$ compile调用之前。我尝试使用$ apply调用在我的指令中的$ watch中包含代码,但是当我这样做时,我得到错误&#34; $ apply已在进行中&#34;。

值得注意的是,其范围包含div的控制器具有称为用户的属性。

我做错了什么?

更新

我将html更改为:

<div ng-loading="users">
    {{users[0]}}
    <table>
        <thead>
            <tr>
                <th>Name</th>
                <th>Age</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="user in users">
                <td>{{user.name}}</td>
                <td>{{user.age}}</td>
            </tr>
        </tbody>
    </table>
</div>

加载完成后,div的内容将替换为数组中第一个用户的toString,其中包含所有正确的信息,然后是空表。这似乎是ng-repeat ...

的一个问题

2 个答案:

答案 0 :(得分:2)

可能采用不同的方法 - 在Angular中,通常不首选DOM操作。 鉴于Angular的双向数据绑定,html中的条件显示/隐藏是否会在让Angular处理细节的同时完成所需的结果?

例如

<div ng-show="users">
    <table>
        <thead>
            <tr>
                <th>Name</th>
                <th>Age</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="user in users">
                <td>{{user.name}}</td>
                <td>{{user.age}}</td>
            </tr>
        </tbody>
    </table>
</div>
<div class="spinner" ng-hide="users">
    <div class="rect1"></div>
    <div class="rect2"></div>
    <div class="rect3"></div>
    <div class="rect4"></div>
    <div class="rect5"></div>
</div>

答案 1 :(得分:0)

不是获取html内容并附加元素内容,只需将微调器附加到内容并使css更改显示在顶部,一旦加载完成,只需删除微调器元素,如下所示。

app.directive('ngLoading', function ($compile) {

          var loadingSpinner = '<div class="spinner">' + 
            '<div class="rect1"></div>' + 
            '<div class="rect2"></div>' +
            '<div class="rect3"></div>' +
            '<div class="rect4"></div>' +
            '<div class="rect5"></div></div>';

          return {
          restrict: 'A',
          link: function (scope, element, attrs) {  

            scope.$watch(attrs.ngLoading, function (val) {
                if (val) {
                    element.append(loadingSpinner);
                } else {
                    element.find('div.spinner').detach();
                }
            });
          }
        };
      });