Angular2,模板仅在使用 ngAfterContentInit 或 ngAfterViewInit 函数时部分执行
Angular2, templates are only partially executed when using ngAfterContentInit or ngAfterViewInit functions
当试图访问文档的 DOM 时,我发现模板只执行了一部分。如果我使用 setTimeout
我可以解决这个问题,但是正确的方法是什么?
import { Component, Input, AfterContentInit } from '@angular/core';
import { AppService } from './app.service';
@Component({
selector: 'tabs',
templateUrl: './templates/app.html',
providers: [ AppService ]
})
export class ShowBookmarksComponent implements AfterContentInit {
private addListeners():void {
let timeoutId = setTimeout(() => {
let draggables = document.getElementsByClassName('session');
console.log(draggables);
console.log(draggables.length);
for (let i = 0; i < draggables.length; i++) {
console.log(i+' '+draggables.length)
}
clearTimeout(timeoutId);
}, 1000);
}
ngAfterContentInit() {
this.appService.getBookmarkLists(this.sessions)
.then(() => this.appService.getCurrentTabs(this.current_tabs))
.then(() => this.addListeners());
}
}
appService
正在提供模板将用于显示 html 的数据。模板:
<section class="current_tabs">
<div class="session" *ngFor="let current_tab of get_keys(current_tabs);">
<div class="whatever"></div>
</div>
</section>
<section class="current_bookmarks">
<div class="session" *ngFor="let session of get_keys(sessions);">
<div class="whatever"></div>
</div>
</section>
不知何故*,对应于sessions
的部分被填充,但current_tabs
的部分尚未填充。在调用 addListeners
之前 this.sessions
和 this.current_tabs
都已正确填写
*在 setTimeout
之前执行的 console.log(document.documentElement.innerHTML)
也看到了
<section class="current_tabs">
<!--template bindings={
"ng-reflect-ng-for-of": ""
}-->
</section>
<section class="current_bookmarks">
<!--template bindings={
"ng-reflect-ng-for-of": "my_session_201 etc etc etc (correctly filled)
(在setTimeout中执行时,两者都正确填写)
在代码中,我想要的是正确检索 let draggables = document.getElementsByClassName('session');
,但我没有得到 <section class="current_tabs">
中定义的那些,因为它尚未填充
编辑:更多核心
get_keys(obj : any) : Object {
return Object.keys(obj);
}
AfterViewChecked 被 angular 频繁调用以在新数据可用时更新页面状态(绑定、ajax 请求等)。您应该尝试将您的代码放在 AfterContentInit 中,当所有外部数据加载到页面时调用它。
见https://angular.io/docs/ts/latest/api/core/index/AfterContentInit-class.html
@GünterZöchbauer 在 中解决了。问题是在这两个函数之间
.then(() => this.appService.getCurrentTabs(this.current_tabs))
.then(() => this.addListeners());
渲染器需要显示视图。所以我应该在更新视图时调用 addListeners
。完成
.then(() => {
this.cdr.detectChanges();
this.addListeners();
});
您需要等到 current_tabs
设置完毕,然后显式调用更改检测 (detectChanges()
),之后您可以直接添加侦听器:
constructor(private cdRef:ChangeDetectorRef){}
ngOnInit() {
this.appService.getBookmarkLists(this.sessions)
.then(() => this.appService.getCurrentTabs(this.current_tabs))
.then(() => {
this.cdRef.detectChanges();
this.addListeners();
});
}
当试图访问文档的 DOM 时,我发现模板只执行了一部分。如果我使用 setTimeout
我可以解决这个问题,但是正确的方法是什么?
import { Component, Input, AfterContentInit } from '@angular/core';
import { AppService } from './app.service';
@Component({
selector: 'tabs',
templateUrl: './templates/app.html',
providers: [ AppService ]
})
export class ShowBookmarksComponent implements AfterContentInit {
private addListeners():void {
let timeoutId = setTimeout(() => {
let draggables = document.getElementsByClassName('session');
console.log(draggables);
console.log(draggables.length);
for (let i = 0; i < draggables.length; i++) {
console.log(i+' '+draggables.length)
}
clearTimeout(timeoutId);
}, 1000);
}
ngAfterContentInit() {
this.appService.getBookmarkLists(this.sessions)
.then(() => this.appService.getCurrentTabs(this.current_tabs))
.then(() => this.addListeners());
}
}
appService
正在提供模板将用于显示 html 的数据。模板:
<section class="current_tabs">
<div class="session" *ngFor="let current_tab of get_keys(current_tabs);">
<div class="whatever"></div>
</div>
</section>
<section class="current_bookmarks">
<div class="session" *ngFor="let session of get_keys(sessions);">
<div class="whatever"></div>
</div>
</section>
不知何故*,对应于sessions
的部分被填充,但current_tabs
的部分尚未填充。在调用 addListeners
this.sessions
和 this.current_tabs
都已正确填写
*在 setTimeout
console.log(document.documentElement.innerHTML)
也看到了
<section class="current_tabs">
<!--template bindings={
"ng-reflect-ng-for-of": ""
}-->
</section>
<section class="current_bookmarks">
<!--template bindings={
"ng-reflect-ng-for-of": "my_session_201 etc etc etc (correctly filled)
(在setTimeout中执行时,两者都正确填写)
在代码中,我想要的是正确检索 let draggables = document.getElementsByClassName('session');
,但我没有得到 <section class="current_tabs">
中定义的那些,因为它尚未填充
编辑:更多核心
get_keys(obj : any) : Object {
return Object.keys(obj);
}
AfterViewChecked 被 angular 频繁调用以在新数据可用时更新页面状态(绑定、ajax 请求等)。您应该尝试将您的代码放在 AfterContentInit 中,当所有外部数据加载到页面时调用它。
见https://angular.io/docs/ts/latest/api/core/index/AfterContentInit-class.html
@GünterZöchbauer 在
.then(() => this.appService.getCurrentTabs(this.current_tabs))
.then(() => this.addListeners());
渲染器需要显示视图。所以我应该在更新视图时调用 addListeners
。完成
.then(() => {
this.cdr.detectChanges();
this.addListeners();
});
您需要等到 current_tabs
设置完毕,然后显式调用更改检测 (detectChanges()
),之后您可以直接添加侦听器:
constructor(private cdRef:ChangeDetectorRef){}
ngOnInit() {
this.appService.getBookmarkLists(this.sessions)
.then(() => this.appService.getCurrentTabs(this.current_tabs))
.then(() => {
this.cdRef.detectChanges();
this.addListeners();
});
}