Angular2, templates are only partially executed when using ngAfterContentInit or ngAfterViewInit functions

和自甴很熟 提交于 2019-12-24 08:03:06

问题


When trying to access to a DOM of the document, I find that the template is only partially executed. If I use a setTimeout I can workaround the problem, but how is the proper way to do it?

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 is providing data that the template will use to display the html. The template:

<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>

And somehow*, the part corresponding to sessions is filled but the part of current_tabs is not yet filled. Both this.sessions and this.current_tabs are correctly filled before calling addListeners

*seen as well by console.log(document.documentElement.innerHTML) executed before the setTimeout

<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)

(when executing it inside the setTimeout, both are correctly filled)

In the code, what I want is to get the let draggables = document.getElementsByClassName('session'); correctly retrieved, but I am not getting the ones defined within <section class="current_tabs"> since it is not yet filled

EDIT: more core Iterate over TypeScript Dictionary in Angular 2

get_keys(obj : any) : Object {
    return Object.keys(obj);
}

回答1:


You need to wait until the current_tabs are set, then invoke change detection explicitly (detectChanges()), then you can add the listeners directly afterwards:

constructor(private cdRef:ChangeDetectorRef){}

ngOnInit() {
    this.appService.getBookmarkLists(this.sessions)
    .then(() => this.appService.getCurrentTabs(this.current_tabs))
    .then(() => {
      this.cdRef.detectChanges();
      this.addListeners();
    });
}



回答2:


AfterViewChecked is called very frequently by angular to update state of the page when new data is available (bindings, ajax requests etc). You should try to put your code in AfterContentInit which is called when all external data is loaded to page.

see https://angular.io/docs/ts/latest/api/core/index/AfterContentInit-class.html




回答3:


Solved in Angular2, HostListener, how can I target an element? can I target based on class? by @GünterZöchbauer. The problem is that between the 2 functions

    .then(() => this.appService.getCurrentTabs(this.current_tabs))
    .then(() => this.addListeners());

the renderer needs to display the view. So I should call addListeners when the view is updated. Done with

    .then(() => {
        this.cdr.detectChanges();
        this.addListeners();
     });


来源:https://stackoverflow.com/questions/41695838/angular2-templates-are-only-partially-executed-when-using-ngaftercontentinit-or

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!