2012-08-14 103 views
28

如何在渲染模板後運行方法$scope.myWork()?我想設置$scope.value,之後我需要用JQuery改變一些東西(例如在模板內容的DOM中)。 $scope.$watch('value', function(){....})正在「render」之前工作(模板的DOM尚不可用)。謝謝。AngularJS:渲染後回調(渲染後使用DOM)

回答

20

創建一個directive,它在鏈接函數中運行您的代碼。 鏈接功能在模板生成後調用。

請參閱ng-click得到一個想法。

+0

還有就是我的例子,不工作 - http://jsfiddle.net/C6SUv/7/(爲什麼ISN」在每次渲染之後調用t $ scope.afterRender?)。 – user1595465 2012-08-14 15:07:45

+0

,因爲鏈接函數在呈現元素之後被調用一次,而不是在每次呈現角度之後調用。爲什麼你不能創建指令,使用jQuery進行更改並更新角度?在控制器內部操作DOM並不是一個好的做法 – 2012-08-14 16:56:33

+0

嗯。我必須用固定高度滾動div。我有按鈕在字段列表中移動光標。我在ngClick中設置了$ scope.value,然後我需要在正確的位置滾動(通過scrollTop)。這就是爲什麼我想用控制器內部的DOM來操作的原因。任何想法? – user1595465 2012-08-14 17:10:15

15

我用terminaltransclude在屬性指令調用一個作用域方法的模型被更新後視圖渲染(在我的情況下,$ Resource.query後調整大小的iframe):

.directive('postRender', [ '$timeout', function($timeout) { 
var def = { 
    restrict : 'A', 
    terminal : true, 
    transclude : true, 
    link : function(scope, element, attrs) { 
     $timeout(scope.resize, 0); //Calling a scoped method 
    } 
}; 
return def; 
}]) 

$超時是黑魔法。它應該可以聲明JS方法作爲屬性值和$解析它。

於是我就用它在一個ng-repeat(在我的情況下,樹遞歸渲染):

<div post-render ng-repeat="r in regions | orderBy:'name'" ng-include="'tree_region_renderer.html'"> 
2

延回答上面的工作,但請注意,在新的AngularJS版本(例如1.2.3)你由於它們都具有transclude:true,因此不能將該postRender指令與ng-repeat組合爲同一標記上的屬性。在這種情況下,您必須刪除transclude或使用postRender指令屬性設置單獨的標記。
在使用terminal時也要注意屬性的優先級:true,因爲在同一個標​​簽上可能由於較高優先級的屬性而導致屬性無效。

7

我也有這個問題,其他解決方案對我來說工作不好,而且好像是量角器必須解決的事情。 Protractor's client-side scripts的快速回顧顯示它使用angular.getTestability(element)來知道何時實際運行測試。該方法等待,直到沒有掛起超時或http請求,然後運行您的回調。這裏是我的指令:

export function afterRender ($timeout) { 
"ngInject"; 
    return { 
     restrict: 'A', 
     terminal: true, 
     link: function (scope, element, attrs) { 
     angular.getTestability(element).whenStable(function() { 
      console.log('[rendered]'); 
     }); 
     } 
    }; 
} 
+1

因爲你正在Angular應用程序中運行,所以你可以簡單地注入'$ browser'並註冊一個帶有'notifyWhenNoOutstandingRequests()'方法的回調函數。但請注意,這依賴於某些未公開的私有API,並可能在不通知的情況下中斷。 – gkalpak 2016-02-25 11:46:59

-2

當找到一個方法來配置DOM渲染時,我發現了這個頁面。我發現了一個非常簡單的解決方案,正在爲我的用例工作。

將一個ng-init處理程序附加到DOM元素和處理函數中,使用$ timeout來執行執行。例如:

HTML:

<div ng-init="foo()"> 

JS:

$scope.foo = function() { 
    $timeout(function() { 
     // This code runs after the DOM renders 
    }); 
});