AngularJS:$viewContentLoaded 在局部视图出现之前触发 [英] AngularJS: $viewContentLoaded fired before partial view appears

查看:30
本文介绍了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("内容加载");console.log($("#loginForm"));//断点在这里});[...]

我想我做错了什么,因为如果这是一个常见的错误,就必须有更多关于 stackoverflow 的帖子.

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

角度.module('docinvoiceClientAngularjsApp', ['ui.router','ngAnimate','ngCookies','ngResource','ngMessages','ngRoute','ngSanitize','ngTouch']).config(function ($routeProvider, $stateProvider) {$stateProvider.state('登录', {网址:'/',templateUrl: 'components/login/loginView.html',控制器:'登录控制器'}).run(['$state', function ($state) {$state.transitionTo('登录');}])[...]

感谢任何帮助.感谢和亲切的问候

更新 1: 我将错误归结为以下用例:loginView.html 如下所示:

<form id="loginForm" ng-submit="login(credentials)" ng-if="session.token == undefined">[...]

一旦我从 div 标签中删除 ng-if,它就会按预期工作.该事件在 DOM 渲染后触发,从而 jQuery 找到该元素.如果 ng-if 附加到 div 标签,则行为如最初所述.

更新 2: 正如所承诺的,我添加了一个工作演示,显示添加 ng-if 指令时的不同行为.任何人都可以指出我正确的方向吗?不要像这样坚持登录表单,因为还有更多的用例,我想根据某些表达式删除视图的某些部分,并在部分视图准备好后做一些 JavaScript 的事情.

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

解决方案

这与 angular 摘要循环有关,它是关于 angular 在幕后如何工作、数据绑定等.有很好的教程解释了这一点.

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

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

在此处修复了演示:http://codepen.io/anon/pen/JoYPdv

但我强烈建议你使用指令来做任何 DOM 操作,控制器不适合这个.以下是如何执行此操作的示例:在 AngularJS 中轻松操作 dom - 单击按钮,然后将焦点设置到输入元素

For a partial view I want to do some JavaScript stuff that I usually would do with $(document).ready(function() {...}), e.g. bind venet listeners to elements. I know that this doesn't work for AngularJS and partial views loaded into the "root" view.

Thus I added a listener to the controller that listens to the $viewContentLoaded event. The listener's function is invoked, so the event is fired but it seems to me as if it is before the partial view is rendered. Neither do I see the elements when I set a breakpoint in the listener's function and debug it with firebug, nor does the jquery selection within the function find the partial view's elements.

This is what the controller looks like:

angular.module('docinvoiceClientAngularjsApp')
  .controller('LoginController', function ($scope, $rootScope) {

$scope.$on('$viewContentLoaded', function(event) {
  console.log("content loaded");
  console.log($("#loginForm"));   // breakpoint here 
});

[...]

I guess that I am doing something wrong as there had to be more posts on stackoverflow if this is a common bug.

As I am using ui-router and ui-view, I will give you an excerpt of the routing file:

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

 [...]

Any help is appreciated. Thanks and kind regards

UPDATE 1: I stripped the error down to the following usecase: The loginView.html looks like the following:

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

[...]

As soon as I remove the ng-if from the div tag, it works as expected. The event is triggered after the DOM is rendered, thus jQuery finds the element. If the ng-if is attached to the div tag, the behaviour is as first described.

UPDATE 2: As promised I added a working demo that shows the different behaviour when adding a ng-if directive. Can anyone point me the right direction? Don't stick to the login form as such, as there are many more use cases where I want to remove certain parts of a view based on some expression and do some JavaScript stuff after the partial view is ready.

You can find the working demo here: Demo

解决方案

This is related to angular digest cycle, it's about how angular works underneath the hood, data binding etc. There are great tutorials explaining this.

To solve your problem, use $timeout, it will make the code execute on the next cycle, whem the ng-if was already parsed:

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

Fixed demo here: http://codepen.io/anon/pen/JoYPdv

But I strongly advise you to use directives do any DOM manipulation, the controller isn't for that. Here is a example of how do this: Easy dom manipulation in AngularJS - click a button, then set focus to an input element

这篇关于AngularJS:$viewContentLoaded 在局部视图出现之前触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆