Tengo una plantilla angular en el DOM. Cuando mi controlador obtiene nuevos datos de un servicio, actualiza el modelo en $ scope y vuelve a representar la plantilla. Todo bien hasta ahora.
El problema es que también necesito hacer un poco de trabajo adicional después de que la plantilla se haya vuelto a procesar y esté en el DOM (en este caso, un complemento jQuery).
Parece que debería haber un evento para escuchar, como AfterRender, pero no puedo encontrar tal cosa. Tal vez una directiva sería un camino a seguir, pero también parecía dispararse demasiado pronto.
Aquí hay un jsFiddle que describe mi problema: Fiddle-AngularIssue
== ACTUALIZACIÓN ==
Basado en comentarios útiles, en consecuencia, cambié a una directiva para manejar la manipulación del DOM e implementé un modelo $ watch dentro de la directiva. Sin embargo, todavía tengo el mismo problema básico; el código dentro del evento $ watch se dispara antes de que la plantilla se haya compilado e insertado en el DOM, por lo tanto, el complemento jquery siempre evalúa una tabla vacía.
Curiosamente, si elimino la llamada asíncrona, todo funciona bien, por lo que es un paso en la dirección correcta.
Aquí está mi Fiddle actualizado para reflejar estos cambios: http://jsfiddle.net/uNREn/12/
fuente
Respuestas:
Esta publicación es antigua, pero cambio su código a:
ver jsfiddle .
Espero que te ayude
fuente
Primero, el lugar correcto para meterse con el renderizado son las directivas. Mi consejo sería envolver DOM manipulando complementos jQuery por directivas como esta.
Tuve el mismo problema y se me ocurrió este fragmento. Utiliza
$watch
y$evalAsync
para garantizar que su código se ejecute después de queng-repeat
se hayan resuelto las directivas y se hayan{{ value }}
procesado las plantillas .Espero que esto pueda ayudarlo a evitar un poco de lucha.
fuente
link
función con atemplateUrl
.Siguiendo los consejos de Misko, si desea una operación asincrónica, entonces en lugar de $ timeout () (que no funciona)
use $ evalAsync () (que funciona)
Violín . También agregué un enlace "eliminar fila de datos" que modificará $ scope.assignments, simulando un cambio en los datos / modelo, para mostrar que cambiar los datos funciona.
La sección Tiempo de ejecución de la página Descripción general conceptual explica que evalAsync debe usarse cuando necesita que ocurra algo fuera del marco de la pila actual, pero antes de que se muestre el navegador. (Adivinando aquí ... el "marco de pila actual" probablemente incluye actualizaciones de Angular DOM). Use $ timeout si necesita que ocurra algo después de que se visualice el navegador.
Sin embargo, como ya descubrió, no creo que haya necesidad de una operación asincrónica aquí.
fuente
$scope.$evalAsync($scope.assignmentsLoaded(data));
no tiene ningún sentido IMO. El argumento para$evalAsync()
debería ser una función. En su ejemplo, está llamando a la función en el momento en que una función debe registrarse para su posterior ejecución.He encontrado que la solución más simple (barata y alegre) es simplemente agregar un espacio vacío con ng-show = "someFunctionThatAlwaysReturnsZeroOrNothing ()" al final del último elemento renderizado. Esta función se ejecutará cuando se verifique si se debe mostrar el elemento span. Ejecute cualquier otro código en esta función.
Me doy cuenta de que esta no es la forma más elegante de hacer las cosas, sin embargo, funciona para mí ...
Tuve una situación similar, aunque ligeramente invertida donde necesitaba eliminar un indicador de carga cuando comenzó una animación, en dispositivos móviles, el inicio angular era mucho más rápido que la animación que se mostraba, y el uso de una capa ng era insuficiente ya que el indicador de carga era insuficiente. eliminado mucho antes de que se muestren los datos reales. En este caso, acabo de agregar la función my return 0 al primer elemento renderizado, y en esa función volteé la var que oculta el indicador de carga. (por supuesto, agregué un ng-hide al indicador de carga activado por esta función.
fuente
$anchorScroll
que se llamara al servicio integrado después de que se renderizara el DOM y nada parecía funcionar pero esto. Hackish pero funciona.Creo que está buscando $ evalAsync http://docs.angularjs.org/api/ng.$rootScope.Scope#$evalAsync
fuente
Finalmente encontré la solución, estaba usando un servicio REST para actualizar mi colección. Para convertir la tabla de datos jquery es el siguiente código:
fuente
He tenido que hacer esto con bastante frecuencia. Tengo una directiva y necesito hacer algunas cosas jquery después de que las cosas del modelo estén completamente cargadas en el DOM. así que pongo mi lógica en el enlace: función de la directiva y envuelvo el código en un setTimeout (function () {.....}, 1); setTimout se activará después de cargar el DOM y 1 milisegundo es el tiempo más corto después de cargar el DOM antes de que se ejecute el código. Esto parece funcionar para mí, pero deseo que angular genere un evento una vez que se cargó una plantilla para que las directivas utilizadas por esa plantilla puedan hacer cosas jquery y acceder a elementos DOM. espero que esto ayude.
fuente
También puede crear una directiva que ejecute su código en la función de enlace.
Ver esa respuesta stackoverflow .
fuente
Ni $ scope. $ EvalAsync () ni $ timeout (fn, 0) funcionaron de manera confiable para mí.
Tuve que combinar los dos. Hice una directiva y también puse una prioridad más alta que el valor predeterminado para una buena medida. Aquí hay una directiva para ello (Nota: uso ngInject para inyectar dependencias):
Para llamar a la directiva, haría esto:
Si desea llamarlo después de que se haya ejecutado un ng-repeat, agregué un espacio vacío en mi ng-repeat y ng-if = "$ last":
fuente
En algunos escenarios donde actualiza un servicio y redirige a una nueva vista (página) y luego su directiva se carga antes de que se actualicen sus servicios, puede usar $ rootScope. $ Broadcast si su $ watch o $ timeout falla
Ver
Controlador
Directiva
fuente
Vine con una solución bastante simple. No estoy seguro de si es la forma correcta de hacerlo, pero funciona en un sentido práctico. Miremos directamente lo que queremos que se represente. Por ejemplo, en una directiva que incluye algunos
ng-repeat
s, estaría atento a la longitud del texto (¡puede que tenga otras cosas!) De párrafos o todo el html. La directiva será así:TENGA EN CUENTA que el código realmente se ejecuta después de representar los cambios en lugar de completar la representación. Pero supongo que en la mayoría de los casos puede manejar las situaciones siempre que ocurran cambios de representación. También podría pensar en comparar
p
la longitud de esta s (o cualquier otra medida) con su modelo si desea ejecutar su código solo una vez después de completar la representación. Agradezco cualquier pensamiento / comentario sobre esto.fuente
Puede usar el módulo 'jQuery Passthrough' de las utilidades angular-ui . Encontré con éxito un complemento de carrusel táctil jQuery a algunas imágenes que recupero asíncrono de un servicio web y las renderizo con ng-repeat.
fuente