2012-08-14 12 views
28

¿Cómo se puede ejecutar un método $scope.myWork() después de la plantilla de renderizado? Quiero configurar el $scope.value y después de eso necesito cambiar algo con JQuery (por ejemplo, en DOM del contenido de la plantilla). $scope.$watch('value', function(){....}) está trabajando el renderizado "antes" (el DOM de la plantilla aún no está disponible). Gracias.AngularJS: devolución de llamada después de renderizar (trabajar con DOM después del procesamiento)

Respuesta

20

Crea un directive que ejecuta tu código en la función de enlace. La función de enlace se invoca después de que se genera la plantilla.

Consulte ng-click para tener una idea.

+0

No es mi ejemplo, que no funciona - http://jsfiddle.net/C6SUv/7/ (¿por qué ISN' t $ scope.afterRender llamada después de cada render?). – user1595465

+0

porque la función de enlace se llama una vez después de que se represente el elemento, no después de cada procesamiento de angular. ¿Por qué no puede crear directivas si realiza los cambios que necesita con jQuery y actualiza angular? Manipular el DOM dentro de los controladores no es una buena práctica –

+0

Hmmmmm. Tengo que desplazar div con la altura del arreglo. Tengo botones para mover el cursor en la lista de campos. Configuré $ scope.value en ngClick y después de eso tengo que desplazarme en la posición correcta (a través de scrollTop). Esa es la razón, por la que quiero manipular con DOM dentro del controlador. ¿Alguna idea? – user1595465

15

utilizo terminal y transclude en una directiva de atributo para llamar a un método de ámbito después de un modelo se actualiza y se hace la vista (en mi caso para cambiar el tamaño de un marco flotante después de un $ Resource.query):

.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; 
}]) 

El $ timeout es magia negra. Es debe ser posible declarar el método JS como el valor del atributo y $ analizarlo.

Así que lo utilizan en un ng-repeat (en mi caso un árbol se representa de forma recursiva):

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

Jens respuesta anterior funcionará, pero tenga en cuenta que en las versiones más recientes AngularJS (por ejemplo, 1.2.3) se no puede tener esa directiva postRender en combinación con ng-repeat como atributos en la misma etiqueta ya que ambos tienen transclude: true. En ese caso, debe eliminar transclude o tener una etiqueta separada con el atributo directivo postRender.
Tenga también en cuenta la prioridad de los atributos al usar terminal: verdadero, ya que puede terminar teniendo un atributo no efectivo debido a uno priorizado superior en la misma etiqueta.

7

También tuve este problema, otras soluciones no funcionaron bien para mí, y parecía ser el tipo de cosas que Transportador debe haber resuelto. Una revisión rápida de Protractor's client-side scripts muestra que usa angular.getTestability(element) para saber cuándo ejecutar realmente las pruebas. El método espera hasta que no haya tiempos de espera pendientes o solicitudes http y luego ejecuta su devolución de llamada. Aquí está mi directiva:

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

Dado que se está ejecutando dentro de la aplicación Angular, simplemente puede insertar '$ browser' y registrar una devolución de llamada con su método' notifyWhenNoOutstandingRequests() '. Sin embargo, tenga en cuenta que esto se basa en algunas API privadas no documentadas y podría romperse sin previo aviso. – gkalpak

-2

Encontré esta página cuando buscaba una forma de perfilar DOM. Encontré una solución muy simple que funciona para mi caso de uso.

Adjunte un controlador ng-init al elemento DOM y en la función del controlador, use $ timeout para ceder la ejecución. Ejemplo:

HTML:

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

JS:

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