AngularJS:$ viewContentLoaded在部分视图出现之前触发

对于局部视图,我想做一些我通常用$(document).ready(function() {...})做的JavaScript,比如将venet监听器绑定到元素。 我知道这对AngularJS和加载到“根”视图中的部分视图不起作用。

因此,我向侦听器添加了一个侦听器,侦听器监听$viewContentLoaded事件。 调用侦听器的函数,因此事件被触发但在我看来好像是在呈现局部视图之前。 当我在侦听器的函数中设置断点并使用firebug调试它时,我也没有看到元素,函数中的jquery选择也没有找到局部视图的元素。

这就是控制器的样子:

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

我想我做错了,因为如果这是一个常见的错误,必须在stackoverflow上发布更多post。

当我使用ui-routerui-view时 ,我会给你一个路由文件的摘录:

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

任何帮助表示赞赏。 谢谢和亲切的问候

更新1:我将错误删除到以下用例:loginView.html如下所示:

 
[...]

一旦我从div标签中删除ng-if ,它就会按预期工作。 在呈现DOM之后触发事件,因此jQuery找到该元素。 如果ng-if附加到div标签,则行为如首先描述的那样。

更新2:正如所承诺的,我添加了一个工作演示,显示添加ng-if指令时的不同行为。 谁能指出我正确的方向? 不要坚持使用登录表单,因为有更多的用例,我想根据某些表达式删除视图的某些部分,并在部分视图准备好后执行一些JavaScript操作。

你可以在这里找到工作演示: 演示

这与角度消化周期有关,它是关于角度如何在引擎盖下工作,数据绑定等。有很好的教程解释这一点。

要解决您的问题,请使用$ timeout,它将使代码在下一个周期执行,因为ng-if已经被解析:

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

修复了这里的演示: http : //codepen.io/anon/pen/JoYPdv

但我强烈建议你使用指令做任何DOM操作,控制器不是为了这个。 下面是一个如何执行此操作的示例: AngularJS中的简易dom操作 – 单击按钮,然后将焦点设置为输入元素

我已经在指令的帮助下解决了这个问题。 将一个direcitve添加到您的元素(如

)并对相应指令中的元素进行操作,如下所示,

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

我还尝试了状态提供程序事件,如$stateChangeSuccess$viewContentLoaded但无法解决问题。 因为在这些事件被解雇之后,它需要花时间在DOM上呈现。

所以,我们可以遵循这种方法,它提供了完美的结果和在Angular JS中实现的正确方法:)

这是哈迪斯的答案有点晚,但可能会帮助其他人。 我设置了一个服务,我稍后可以从控制器或指令调用它。

 '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(); } }; });