当前位置: 代码迷 >> JavaScript >> 如何在angularJS控制器中将回调函数传递给$ compile服务?
  详细解决方案

如何在angularJS控制器中将回调函数传递给$ compile服务?

热度:78   发布时间:2023-06-05 15:51:46.0

我还在学习AngularJS。

我用于加载角度对象的JS文件中具有以下功能:

app.controller("myController", ['$scope', '$compile', function ($scope, $compile) {
var $theContainer = $('.container123');
...

this.loadStuff = function () {
                $compile('<layout-withbars></layout-withbars>')($scope, function (clonedElement, $scope) {
                    $theContainer.html(clonedElement); //  **this line is where my tests show a runtime issue **
                    setTimeout(function () {
                        $('.progress-bar').each(function () {
                           var $bar = $(this);
                           $bar.css('width', $bar.attr('aria-valuenow') + '%');
                            });
                        }, 1500);
                });
        };
}]);

该指令本身可以正确加载,其中包含引导进度条。 此“ loadStuff”函数的目标是加载指令,然后使用默认的引导程序过渡使进度条从0%完成更改为X%完成。

如果我在页面上调用此块( 块1 ),则会触发我需要的行为:

 $('.progress-bar').each(function () {
                           var $bar = $(this);
                           $bar.css('width', $bar.attr('aria-valuenow') + '%');
                            });

layout-withbars.html:

<div ng-repeat="aProgressbar in progressbars" class="progress">
  <div class="progress-bar" role="progressbar" aria-valuenow="{{aProgressbar.complete}}" style="width: 0%;">
  </div>
</div>

问题:

我必须在对块1的控制器调用周围附加“ setTimeout”函数。 我这样做是因为经过一些测试,我相信$ compile服务指令注入/处理在描述的块1被调用后完成。 我在上面的代码中突出显示了它。

这里有一种组织执行时间的方法吗? 在某些情况下,我的1.5秒延迟可能还不够。

我在从$ compile服务中寻找回调函数。 我相信它是“ postLink”。 我尝试实现它,但是还没有运气。

在$ compile服务指令注入/处理完成执行之后,发出块1执行的最佳方法是什么?

顺便说一句,我还在第1块周围尝试了此操作,但没有成功:

$theContainer.html(clonedElement).promise().done(function(){
...
}

是的,我坚持要删除毫无意义的Jquery代码和$compile误用。 因此,不需要超时的回调函数。

除了可以手动告诉angular来编译指令之外,还可以通过ng-if让它出现在DOM中。 非常适合在DOM中动态添加或删除数量有限的指令(在您的情况下为一个)的情况。

<layout-withbars ng-if="showProgress"></layout-withbars>

所以loadStuff应该只设置$scope.showProgress = true;
请记住,当表达式为falsy时,与ng-show相反, ng-if实际上删除了该元素。 因此,每当它变为truthy并将元素添加到DOM时,该指令将再次链接。 在指令的link (或实际上为postLink )处理程序中postLink结论与您试图在setTimeout()实现的处理程序完全相同。 但是,由于存在允许对元素样式进行数据绑定的指令,因此不再需要此操作。

<div class="progress-bar" 
     role="progressbar" 
     ng-style="{width: aProgressbar.complete + '%';">

这样,一旦模型中的数据被更新,宽度将被更新。

我不太了解不愿意使用$compile服务...它没有施加任何其他延迟。 在我的测试中,我观察到它使浏览器仅在使用$compile调用注入指令时才加载指令模板,因此,加载实际上比使用ng-if更快。

无论如何,基里尔·斯拉汀(Kirill Slatin)的回答为我指明了正确的方向:

为了在由angular指令生成的DOM元素上执行函数,指令定义为angular的“指令编译” 之前之后提供了回调函数。 我从得到 。

此处的解决方案是将块1重构为postLinkpreLink函数中的指令的link属性。 之后,不再发生执行时间问题:

app.directive('layoutWithbars', function () {
        return {
            restrict: 'E',
            templateUrl: 'layout-withbars.html',
             link: {
                pre: function preLink(scope, iElement, iAttrs, controller) {
                   for (var i=0; i< scope.progressBars.length; i++)
                      scope.progressBars[i].range = 0;
                },
                post: function postLink(scope, iElement, iAttrs, controller) {
                   $timeout(function () {
                   for (var i=0; i< scope.progressBars.length; i++)
                      scope.progressBars[i].range = scope.progressBars[i].complete;
                }, 100);

            }
        }
        };
    });

并且指令主体将具有以下数据绑定,因此将更像angularJS:

<div class="progress" ng-repeat="aProgressBar in progressBars">
  <div class="progress-bar" role="progressbar" 
      aria-valuenow="{{aProgressBar.complete}}" 
      aria-valuemin="0" 
      aria-valuemax="100" 
      ng-style="{width: aProgressBar.range +'%'}">
  </div>
</div>
  相关解决方案