Para una vista parcial quiero hacer algo de JavaScript cosas que normalmente haría con $(document).ready(function() {...}), por ejemplo, enlazar venet oyentes a los elementos. Sé que esto no funciona para AngularJS y vistas parciales cargado en la «raíz» de la vista.

Así que he añadido un detector para el controlador que se escucha a la $viewContentLoaded evento. El oyente se invoca la función, por lo que se desencadena el evento, pero a mí me parece como si antes de la vista parcial se representa. Tampoco veo a los elementos cuando me establezca un punto de interrupción en la escucha de la función y la depuración con firebug, ni tampoco el de jquery selección dentro de la función de encontrar la visión parcial de los elementos.

Esto es lo que el controlador se parece a:

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 como había llegado a ser más de los puestos en stackoverflow si este es un error común.

Como estoy usando de la interfaz de usuario del router y ui-view, voy a darle 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 muy apreciada. Gracias y saludos

ACTUALIZACIÓN 1: me quité el error hasta el siguiente caso de uso: La loginView.html el siguiente aspecto:

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

[...]

Tan pronto como puedo quitar el ng-if de la etiqueta div, que funciona como se espera. El evento se activa cuando el DOM está representado, por lo tanto jQuery encuentra el elemento. Si el ng-if se adjunta a la etiqueta div, el comportamiento es descrito por primera vez.

ACTUALIZACIÓN 2: Como prometí he añadido un demo que muestra un comportamiento distinto al agregar un ng-if directiva. Puede alguien me apunte en la dirección correcta? No se adhieren a la forma de inicio de sesión como tal, ya que hay muchos más casos de uso donde quiero quitar ciertas partes de una vista basada en algunos de expresión y hacer algo de JavaScript cosas después de la vista parcial está listo.

Usted puede encontrar el demo aquí: Demo

  • Usted puede crear una directiva para usted DOM cosas.
  • He creado un demo a partir de su código y de que funciona correctamente. La próxima vez, por favor trate de dar la demostración de ti mismo.
  • Muchas gracias por la demo. He actualizado la descripción como me enteré de que la ng-si las causas del diferente comportamiento. ¿Tienes una idea de por qué se comporta de manera diferente? La expresión se evalúa a «true» como puedo ver el formulario de inicio de sesión, sólo un momento demasiado tarde 😉
  • Voy a añadir un demo más tarde y enviar el enlace para una mayor investigación.
  • El DOM es construido de forma iterativa a través de $digerir ciclos. $viewContentLoaded es despedido tan pronto como la interfaz de usuario de vista tiene la plantilla compilada, y el controlador ha sido ejecutado. El dom puede cambiar en los próximos $digerir en respuesta a algo que sucedió en el controlador, o lo que sea. No hay un buen mecanismo para replicar el documento.listo() estilo de jquery.
InformationsquelleAutor Florian | 2014-11-25

3 Comentarios

  1. 44

    Esto está relacionado con angular de digerir ciclo, se trata de cómo angular obras de debajo de la capucha, el enlace de datos etc. Hay buenos tutoriales explicando esto.

    Para resolver su problema, utilice $tiempo de espera, se hará la ejecución del código en el ciclo siguiente, cuando el ng-si ya fue analizado:

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

    Fijo demo aquí: http://codepen.io/anon/pen/JoYPdv

    Pero te aconsejo que para utilizar las directivas de hacer cualquier manipulación del árbol DOM, el controlador no está para eso.
    Aquí está un ejemplo de cómo hacer esto:
    Fácil manipulación del árbol dom en AngularJS – haga clic en un botón, a continuación, establecer el foco a un elemento de entrada

    • Voy a considerar este como el más valioso de la respuesta, ya que proporciona una solución posible y una pista para encontrar más información sobre el ciclo de digerir, a pesar de que estoy usando la directiva ahora.
    • Muy bien explicado! yo era capaz de integrar App.js y AngularJS mediante el código anterior fragmento y también entiende de tiempo de espera de los detalles intrincados.
    • El problema con este enfoque es que en la interfaz de usuario del router $viewContentLoaded incendios para cada vista. Si usted tiene un montón de puntos de vista en una sola página de su código se ejecute varias veces. Es allí una manera de tener que ejecutar sólo una vez cuando TODOS los puntos de vista han cargado?
    • Escribí un conjunto de directivas que registrar sus geometrías con un servicio para habilitar geométrica de navegación alrededor de la página. Se comportó extremadamente impredecible hasta que leí esto. 50msec retraso en la geometría cálculo fijo de mí! Voy a estar en el puesto de observación para un mayor enfoque determinístico.
  2. 1

    Me han resuelto este problema con la ayuda de las Directivas. Añadir una direcitve a su elemento (como <div my-dir></div>) y hacer manipulaciones para el elemento correspondiente de la directiva 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 he tratado de estado proveedor de eventos como $stateChangeSuccess, $viewContentLoaded pero no podía resolver el problema. Porque después de esos sucesos despidieron, es tomar el tiempo para hacer el DOM.

    Así, podemos seguir este enfoque, que da un resultado perfecto y la forma correcta de implementar en Angular JS 🙂

  3. 0

    Esta es una respuesta a Hades un poco tarde, pero podría ayudar a alguien más. Yo instalación de un servicio que yo más tarde será capaz de llamar desde un controlador o de la directiva.

    HTML:

    '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 en la directiva incluyen viewContentLoaded y llamar a la función get con la promesa. No olvides cambiar la aplicación a lo que usted nombre de la aplicación es e incluyen el servicio de archivo a ser cargado.

    HTML:

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

Dejar respuesta

Please enter your comment!
Please enter your name here