Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angularjs Angular JS指令是否有渲染后回调?_Angularjs - Fatal编程技术网

Angularjs Angular JS指令是否有渲染后回调?

Angularjs Angular JS指令是否有渲染后回调?,angularjs,Angularjs,我刚刚收到指令,要拉入一个模板以附加到其元素,如下所示: # CoffeeScript .directive 'dashboardTable', -> controller: lineItemIndexCtrl templateUrl: "<%= asset_path('angular/templates/line_items/dashboard_rows.html') %>" (scope, element, attrs) -> element.pa

我刚刚收到指令,要拉入一个模板以附加到其元素,如下所示:

# CoffeeScript
.directive 'dashboardTable', ->
  controller: lineItemIndexCtrl
  templateUrl: "<%= asset_path('angular/templates/line_items/dashboard_rows.html') %>"
  (scope, element, attrs) ->
    element.parent('table#line_items').dataTable()
    console.log 'Just to make sure this is run'

# HTML
<table id="line_items">
    <tbody dashboard-table>
    </tbody>
</table>
#咖啡脚本
.指令“dashboardTable”,->
控制器:lineItemIndexCtrl
模板URL:“
(范围、元素、属性)->
element.parent('table#line_items')。dataTable()
console.log“只是为了确保它已运行”
#HTML
我还使用了一个名为DataTables的jQuery插件。它的一般用法如下:$('table#some_id').dataTable()。您可以将JSON数据传递到dataTable()调用中以提供表数据,或者您可以在页面上已经有数据,它将完成其余的工作。。我正在做后一个,在HTML页面上已经有了行

但问题是,我必须在DOM就绪后调用表#line_项上的dataTable()。上面我的指令在将模板附加到指令的元素之前调用dataTable()方法。有没有一种方法可以在追加后调用函数

谢谢你的帮助

安迪回答后更新1:

我想确保link方法只有在所有内容都在页面上之后才会被调用,所以我修改了指令进行了一个小测试:

# CoffeeScript
#angular.module(...)
.directive 'dashboardTable', ->
    {
      link: (scope,element,attrs) -> 
        console.log 'Just to make sure this gets run'
        element.find('#sayboo').html('boo')

      controller: lineItemIndexCtrl
      template: "<div id='sayboo'></div>"

    }
#咖啡脚本
#角模(…)
.指令“dashboardTable”,->
{
链接:(范围、元素、属性)->
console.log“只是为了确保它运行”
元素.find('#sayboo').html('boo'))
控制器:lineItemIndexCtrl
模板:“”
}
而且我确实在div#sayboo中看到了“boo”

然后我尝试调用jquerydatatable

.directive 'dashboardTable',  ->
    {
      link: (scope,element,attrs) -> 
        console.log 'Just to make sure this gets run'
        element.parent('table').dataTable() # NEW LINE

      controller: lineItemIndexCtrl
      templateUrl: "<%= asset_path('angular/templates/line_items/dashboard_rows.html') %>"
    }
指令“dashboardTable”,-> { 链接:(范围、元素、属性)-> console.log“只是为了确保它运行” element.parent('table').dataTable()#新行 控制器:lineItemIndexCtrl 模板URL:“ } 那里运气不好

然后我尝试添加一个超时:

.directive 'dashboardTable', ($timeout) ->
    {
      link: (scope,element,attrs) -> 
        console.log 'Just to make sure this gets run'
        $timeout -> # NEW LINE
          element.parent('table').dataTable()
        ,5000
      controller: lineItemIndexCtrl
      templateUrl: "<%= asset_path('angular/templates/line_items/dashboard_rows.html') %>"
    }
指令“dashboardTable”($timeout)-> { 链接:(范围、元素、属性)-> console.log“只是为了确保它运行” $timeout->#新行 element.parent('table').dataTable() ,5000 控制器:lineItemIndexCtrl 模板URL:“ }
这就行了。所以我想知道非计时器版本的代码出了什么问题

您可以使用“link”函数,也称为postLink,它在放入模板后运行

app.directive('myDirective', function() {
  return {
    link: function(scope, elm, attrs) { /*I run after template is put in */ },
    template: '<b>Hello</b>'
  }
});
app.directive('myDirective',function(){
返回{
link:function(scope、elm、attrs){/*我在模板放入*/}后运行,
模板:“你好”
}
});

如果你打算制定指令,请仔细阅读这篇文章,这是一个很大的帮助:

我也有同样的问题,我相信答案确实是否定的。请看,还有一些

Angular可以跟踪它为操作DOM而进行的所有函数调用是否都已完成,但由于这些函数可能触发异步逻辑,而这些逻辑在返回后仍在更新DOM,因此Angular不可能知道这一点。任何回调有时都可能起作用,但依靠它是不安全的

我们用setTimeout试探性地解决了这个问题,正如您所做的那样


(请记住,并非所有人都同意我的观点-你应该阅读上面链接上的评论,看看你的想法。)

我也有同样的问题,但使用Angular+DataTable和
fnDrawCallback
+$compiled嵌套指令。我在我的
fnDrawCallback
函数中放置了$timeout来修复分页渲染

在示例之前,基于行\分组源:

var myDrawCallback = function myDrawCallbackFn(oSettings){
  var nTrs = $('table#result>tbody>tr');
  for(var i=0; i<nTrs.length; i++){
     //1. group rows per row_grouping example
     //2. $compile html templates to hook datatable into Angular lifecycle
  }
}
var myDrawCallback=函数myDrawCallbackFn(oSettings){
var nTrs=$(“表#结果>正文>tr”);

对于(var i=0;i我使用以下指令得到了这个结果:

app.directive('datatableSetup', function () {
    return { link: function (scope, elm, attrs) { elm.dataTable(); } }
});
app.directive('aDirective', function () {
    return {
        scope: {
            input: '=',
            control: '='
        },
        link: function (scope, element) {
            function functionThatNeedsInput(){
                //use scope.input here
            }
            if ( scope.input){ //We already have input 
                functionThatNeedsInput();
            } else {
                scope.control.init = functionThatNeedsInput;
            }
          }

        };
})
$scope.control = {};
...
$scope.input = 'some data could be async';
if ( $scope.control.functionThatNeedsInput){
    $scope.control.functionThatNeedsInput();
}
在HTML中:

<table class="table table-hover dataTable dataTable-columnfilter " datatable-setup="">
如果未提供第二个参数“delay”,则默认行为是在DOM完成渲染后执行函数。因此,使用$timeout代替setTimeout:

$timeout(function () {
    //DOM has finished rendering
});

虽然我的答案与datatables无关,但它解决了DOM操作的问题,例如jQuery插件初始化用于以异步方式更新内容的元素的指令

不需要实现超时,只需添加一个可以监听内容更改(甚至额外的外部触发器)的手表即可

在我的例子中,当ng重复创建了我的内部DOM之后,我使用这个变通方法初始化了一个jQuery插件——在另一个例子中,我使用它只是在controller上更改scope属性之后操作DOM

HTML:

注意:在我的directive watch属性中,可以想象任何任意表达式,而不是将myContent变量强制转换为bool


注意:像上述示例中那样隔离作用域对于每个元素只能执行一次-尝试在同一元素上使用多个指令执行此操作将导致$compile:multidir错误-请参阅:

没有一个适合我的解决方案接受使用超时。这是因为我使用的模板是动态调用的在postLink期间正在创建y

但是,请注意,当超时将调用的函数添加到浏览器队列时,可能会出现“0”的超时,这将在角度渲染引擎之后发生,因为该函数已经在队列中


指的是:

这是一个指令,它指示在浅渲染之后编程的动作。浅层的意思是,它将在元素渲染之后进行评估,这将与它的内容呈现时无关。因此,如果你需要一些子元素做一个后渲染动作,你应该考虑使用它:

define(['angular'], function (angular) {
  'use strict';
  return angular.module('app.common.after-render', [])
    .directive('afterRender', [ '$timeout', function($timeout) {
    var def = {
        restrict : 'A', 
        terminal : true,
        transclude : false,
        link : function(scope, element, attrs) {
            if (attrs) { scope.$eval(attrs.afterRender) }
            scope.$emit('onAfterRender')
        }
    };
    return def;
    }]);
});
然后你可以做:

或使用任何有用的表达式,如:


我回答这个问题可能会迟到。但还是有人会从我的回答中受益

我有类似的问题,在我的情况下,我不能改变指令,因为它是
app.directive('myDirective', [ function(){
    return {
        restrict : 'A',
        scope : {
            myDirectiveWatch : '='
        },
        compile : function(){
            return {
                post : function(scope, element, attributes){

                    scope.$watch('myDirectiveWatch', function(newVal, oldVal){
                        if (newVal !== oldVal) {
                            // Do stuff ...
                        }
                    });

                }
            }
        }
    }
}]);
define(['angular'], function (angular) {
  'use strict';
  return angular.module('app.common.after-render', [])
    .directive('afterRender', [ '$timeout', function($timeout) {
    var def = {
        restrict : 'A', 
        terminal : true,
        transclude : false,
        link : function(scope, element, attrs) {
            if (attrs) { scope.$eval(attrs.afterRender) }
            scope.$emit('onAfterRender')
        }
    };
    return def;
    }]);
});
$scope.render=false;

//this will fire after load the the page

angular.element(document).ready(function() {
    $scope.render=true;
});
<canvas ng-if="render"> </canvas>
app.directive('aDirective', function () {
    return {
        scope: {
            input: '=',
            control: '='
        },
        link: function (scope, element) {
            function functionThatNeedsInput(){
                //use scope.input here
            }
            if ( scope.input){ //We already have input 
                functionThatNeedsInput();
            } else {
                scope.control.init = functionThatNeedsInput;
            }
          }

        };
})
<a-directive control="control" input="input"></a-directive>
$scope.control = {};
...
$scope.input = 'some data could be async';
if ( $scope.control.functionThatNeedsInput){
    $scope.control.functionThatNeedsInput();
}