Angular指令:如何确保所有嵌套模板和部分加载?

时间:2016-02-16 01:14:41

标签: angularjs templates asynchronous angularjs-directive

假设,我正在制作一个自定义Angular指令,它必须检查和操作其中的DOM树(准确地说:指令所应用的元素下的DOM树)。这种操纵的正确位置是指令的后链接功能。

当指令内的所有HTML内联时,它工作正常。在指令内部出现问题我们有其他指令使用“templateUrl”属性加载模板,或只是“ng-include”指令插入部分。

这些模板和部分是异步加载的。这意味着,在编译阶段,Angular将启动部分加载,并将继续编译,而无需等待加载完成。然后,在父指令链接的那一刻,包含的部分加载可能仍在进行中,因此指令的post-link函数在内部看不到任何内容。

换句话说:指令的post-link函数被设计为在调用它的时候让所有嵌套的DOM都准备就绪,但是使用异步模板并包含这不是这种情况!

模板预加载没有帮助,因为它们仍然是异步访问的。

人们如何克服这一点?

这项任务似乎很常见,但我没有找到一个好的,可靠的解决方案。我是否会错过一些明显的东西?...

更新:我创建了一个Plunk来说明问题。实际上它只复制了ng-include的问题,这是子指令工作的外部模板。在我的项目中它没有,也许这是一个竞争条件,我必须进行更多调查。

2 个答案:

答案 0 :(得分:1)

您可以使用以下命令等待主视图的加载:

$scope.$on('$viewContentLoaded', function () {
  //Here your view content is fully loaded !!
});

如果您使用ng-include加载视图,此技巧与$timeout相同。您应该等待所有部分视图。正确的事件顺序是:

  1. $ viewContentLoaded
  2. $ includeContentRequested
  3. $ timeout
  4. $ includeContentLoaded
  5. 您可以使用$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)。它将在异步加载模板完成加载时调用。 (顺便说一句,这是干净的代码,它不会导致性能问题)