templateurl template route otherwise multiple ejemplo jquery angularjs dom angular-ui-router ready

jquery - template - AngularJS: $ viewContentLoaded activado antes de que aparezca la vista parcial



routing angular 1 (3)

Para una vista parcial, quiero hacer algunas cosas de JavaScript que usualmente haría con $(document).ready(function() {...}) , por ejemplo, unir detectores de venet a elementos. Sé que esto no funciona para AngularJS y las vistas parciales se cargan en la vista "raíz".

Por lo tanto, agregué un oyente al controlador que escucha el evento $viewContentLoaded . Se invoca la función del oyente, por lo que el evento se activa pero me parece que lo es antes de que se muestre la vista parcial. Tampoco veo los elementos cuando establezco un punto de interrupción en la función del oyente y lo depuro con Firebug, ni la selección de jquery dentro de la función encuentra los elementos de la vista parcial.

Este es el aspecto del controlador:

angular.module(''docinvoiceClientAngularjsApp'') .controller(''LoginController'', function ($scope, $rootScope) { $scope.$on(''$viewContentLoaded'', function(event) { console.log("content loaded"); console.log($("#loginForm")); // breakpoint here }); [...]

Supongo que estoy haciendo algo mal ya que tenía que haber más publicaciones en stackoverflow si este es un error común.

Como estoy usando ui-router y ui-view , le daré un extracto del archivo de enrutamiento:

angular .module(''docinvoiceClientAngularjsApp'', [ ''ui.router'', ''ngAnimate'', ''ngCookies'', ''ngResource'', ''ngMessages'', ''ngRoute'', ''ngSanitize'', ''ngTouch'' ]) .config(function ($routeProvider, $stateProvider) { $stateProvider .state(''login'', { url: ''/'', templateUrl: ''components/login/loginView.html'', controller: ''LoginController'' }) .run([''$state'', function ($state) { $state.transitionTo(''login''); }]) [...]

Cualquier ayuda es apreciada. Gracias y saludos cordiales

ACTUALIZACIÓN 1: eliminé el error en el siguiente caso de uso: El archivo loginView.html tiene el siguiente aspecto:

<div id="loginContainer" style="width: 300px"> <form id="loginForm" ng-submit="login(credentials)" ng-if="session.token == undefined"> [...]

Tan pronto como elimine ng-if de la etiqueta div, funciona como se esperaba. El evento se desencadena después de que se representa el DOM, por lo que jQuery encuentra el elemento. Si ng-if está adjuntado a la etiqueta div, el comportamiento es como se describió por primera vez.

ACTUALIZACIÓN 2: Como prometí, agregué una demostración operativa que muestra el comportamiento diferente al agregar una directiva ng-if . ¿Alguien puede señalarme la dirección correcta? No se adhiera al formulario de inicio de sesión como tal, ya que hay muchos más casos de uso en los que deseo eliminar ciertas partes de una vista basadas en alguna expresión y hacer algunas cosas de JavaScript después de que la vista parcial esté lista.

Puede encontrar la demostración funcional aquí: Demo


Esta es una respuesta para Hades un poco tarde, pero podría ayudar a alguien más. Configuro un servicio que luego podré llamar desde un controlador o directiva.

''use strict''; app.factory(''viewContentLoaded'', function($q, $rootScope, $timeout) { var viewContentLoaded = $q.defer(), foo = function() { $timeout(function() { viewContentLoaded.resolve(); // Get all entries }, 100);//Timeout }, checkViewContenLoadedListner = $rootScope.$on(''$viewContentLoaded'', foo);//Rootscope return { getLoaded: function() { return viewContentLoaded.promise; }, removeViewContenListner: function() { //Remove event listern on $viewContentLoaded no $off so call it will unsubscribe it //$rootScope.$off(''$viewContentLoaded'', foo);//Rootscope //Don''t forget to unsubscribe later checkViewContenLoadedListner(); } }; });

En el controlador o directiva incluye viewContentLoaded y llama a la función get con la promesa. No olvides cambiar la aplicación a cualquier nombre de aplicación e incluir el archivo de servicio que se cargará.

viewContentLoaded.getLoaded().then(function(){ //Remove Listner when done viewContentLoaded.removeViewContenListner(); //Your code to run }, function(reason) { //$log.error(reason); });


Esto está relacionado con el ciclo de digestión angular, se trata de cómo funciona el angular debajo del capó, el enlace de datos, etc. Hay excelentes tutoriales que explican esto.

Para resolver su problema, use $ timeout, hará que el código se ejecute en el siguiente ciclo, cuando el ng-if ya fue analizado:

app.controller(''LoginController'', function ($scope, $timeout) { $scope.$on(''$viewContentLoaded'', function(event) { $timeout(function() { $scope.formData.value = document.getElementById("loginForm").id; },0); }); });

Demostración fija aquí: http://codepen.io/anon/pen/JoYPdv

Pero le recomiendo encarecidamente que use directivas para manipular DOM, el controlador no es para eso. Aquí hay un ejemplo de cómo hacer esto: Manipulación dom fácil en AngularJS - haga clic en un botón, luego configure el foco en un elemento de entrada


He resuelto este problema con la ayuda de directivas. Agregue una dirección a su elemento (como <div my-dir></div> ) y realice las manipulaciones al elemento en la directiva respectiva de la siguiente manera:

app.directive(''myDir'', function () { return { restrict: ''A'', link: function (scope, element) { // Do manipulations here with the help of element parameter } }; });

También probé eventos de proveedores estatales como $stateChangeSuccess , $viewContentLoaded pero no pude resolver el problema. Porque después de que esos eventos fueron despedidos, tomar tiempo para renderizar en el DOM.

Por lo tanto, podemos seguir este enfoque que da resultados perfectos y la forma correcta de implementar en Angular JS :)