我创建了一个属性指令,用于替换使用它的元素内部的内容和加载图标,直到作为属性值的变量被评估为未定义的以外的其他内容。该指令的代码是:
.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 ...
的一个问题答案 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();
}
});
}
};
});