AngularJS:$ viewContentLoaded在部分视图出现之前被触发 [英] AngularJS: $viewContentLoaded fired before partial view appears
问题描述
对于局部视图,我想做一些JavaScript东西,我通常会使用 $(document).ready(function(){...})
例如将venet监听器绑定到元素。我知道这不适用于AngularJS和部分视图加载到根视图。
因此,我添加了一个监听器监听 $ viewContentLoaded
事件。调用监听器的函数,因此事件被触发,但在我看来,就像在渲染部分视图之前一样。当我在监听器的函数中设置断点并使用firebug进行调试时,我也不会看到这些元素,函数内的jQuery选择也不会查找部分视图的元素。
这是控制器的样子:
angular.module('docinvoiceClientAngularjsApp')
.controller('LoginController'函数($ scope,$ rootScope){
$ scope。$ on('$ viewContentLoaded',function(event){
console.log(content loaded);
console.log($(#loginForm)); //这里的断点
});
[...]
我想我做错了,因为如果这是一个常见的错误,那么在stackoverflow中有更多的帖子。
当我使用 ui-router 和 ui-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如下所示: p>
< div id =loginContainerstyle =width:300px>
< form id =loginFormng-submit =login(credentials)ng-if =session.token == undefined>
[...]
一旦我删除 ng-if
从div标签,它的工作原理。事件在渲染DOM之后触发,因此jQuery查找元素。如果 ng-if
附加到div标签,行为如第一次描述。
更新2:如所承诺的,我添加了一个工作演示,显示添加 ng-if
指令时的不同行为。任何人都可以指出正确的方向吗?不要这样坚持登录表单,因为还有更多的用例,我想根据一些表达式删除视图的某些部分,并在部分视图准备就绪之后执行一些JavaScript内容。
您可以在这里找到工作演示:演示
这是与角度摘要循环相关的,它是关于帽子下方的角度,数据绑定等。有很好的教程解释这一点。 b
$ b
要解决您的问题,请使用$ 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操作 - 单击一个按钮,然后将焦点设置为输入元素
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屋!