假设,我正在制作一个自定义Angular指令,它必须检查和操作其中的DOM树(准确地说:指令所应用的元素下的DOM树)。这种操纵的正确位置是指令的后链接功能。
当指令内的所有HTML内联时,它工作正常。在指令内部出现问题我们有其他指令使用“templateUrl”属性加载模板,或只是“ng-include”指令插入部分。
这些模板和部分是异步加载的。这意味着,在编译阶段,Angular将启动部分加载,并将继续编译,而无需等待加载完成。然后,在父指令链接的那一刻,包含的部分加载可能仍在进行中,因此指令的post-link函数在内部看不到任何内容。
换句话说:指令的post-link函数被设计为在调用它的时候让所有嵌套的DOM都准备就绪,但是使用异步模板并包含这不是这种情况!
模板预加载没有帮助,因为它们仍然是异步访问的。
人们如何克服这一点?
这项任务似乎很常见,但我没有找到一个好的,可靠的解决方案。我是否会错过一些明显的东西?...
更新:我创建了一个Plunk来说明问题。实际上它只复制了ng-include
的问题,这是子指令工作的外部模板。在我的项目中它没有,也许这是一个竞争条件,我必须进行更多调查。
答案 0 :(得分:1)
您可以使用以下命令等待主视图的加载:
$scope.$on('$viewContentLoaded', function () {
//Here your view content is fully loaded !!
});
如果您使用ng-include加载视图,此技巧与$timeout
相同。您应该等待所有部分视图。正确的事件顺序是:
您可以使用$includeContentRequested
和$includeContentLoaded
与计数器等待所有包含的部分内容:
var nIncludes = 0;
$scope.$on('$includeContentRequested', function (event, templateName) {
nIncludes++;
console.log(nIncludes, '$includeContentRequested', templateName);
});
$scope.$on("$includeContentLoaded", function (event, templateName) {
nIncludes--;
console.log(nIncludes, '$includeContentLoaded', templateName);
if (nIncludes === 0) {
console.log('everything is loaded!!');
// Do stuff here
}
});
我还没有找到另一个更优雅的解决方案。
答案 1 :(得分:0)
使用$timeout
作为外部模板指令(这仍然不适用于ng-include
)。它将在异步加载模板完成加载时调用。 (顺便说一句,这是干净的代码,它不会导致性能问题)