In Angular 2, templates may not be fully executed when utilizing ngAfterContentInit or ngAfterViewInit functions

When I try to access the DOM of the document, I notice that the template is only partially executed. Using a setTimeout helps me bypass the issue temporarily, but what is the correct way to handle this?

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

 }

The appService supplies the data used by the template to display the HTML content.

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

Despite having both this.sessions and this.current_tabs correctly filled before calling addListeners, the part corresponding to sessions is rendered while the part of current_tabs is not yet rendered.

This discrepancy can be observed when executing

console.log(document.documentElement.innerHTML)
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)"

(Within the setTimeout, both sections are correctly filled.)

The goal in the code is to correctly retrieve

let draggables = document.getElementsByClassName('session');
, specifically those defined within
<section class="current_tabs">
which may not be filled yet.

EDIT: Further details on Iterating over TypeScript Dictionary in Angular 2

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

Answer №1

In order for the current_tabs to be properly set, it is crucial to wait before triggering change detection explicitly using detectChanges(). Once this is done, you can proceed to add the listeners as shown in the code snippet below:

constructor(private cdRef:ChangeDetectorRef){}

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

Answer №2

Angular frequently calls AfterViewChecked to update the page's state when new data becomes available (such as bindings or ajax requests). It is recommended to place your code in AfterContentInit, which runs after all external data has been loaded onto the page.

For more information, visit https://angular.io/docs/ts/latest/api/core/index/AfterContentInit-class.html

Answer №3

Resolved in Angular2, HostListener, targeting elements by class with the assistance of @GünterZöchbauer. The issue arose due to timing within the functions.

    .then(() => this.service.updateTabs(this.tabs))
    .then(() => this.attachListeners());

The solution was to ensure that attachListeners is triggered after the view has been rendered. This was achieved through the following approach:

    .then(() => {
        this.renderer.detectChanges();
        this.attachListeners();
     });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

NodeJS function does not pause for the PostgreSQL database call despite using await keyword

I am attempting to recursively insert entries into the database where each entry depends on the previous one (the ID of the previous entry will be the child_id of the next entry). However, I am facing difficulties in getting async/await to work correctly. ...

What is the best way to iterate through an array of arrays using a foreach loop to calculate the total number of specific properties?

For instance, if YieldCalcValues were to look something like this: [ [ 850, 500 ], [ 3, 6 ], [ 1200, 5000 ], [ 526170, 526170 ] ] I am looking to create a foreach loop that calculates the yield per for each product. How can I accomplish this correctly? l ...

various issues with fonts and Uncaught Eval error

I've been encountering multiple font/style errors and an uncaught eval. I have attached a picture for reference. My Angular application is not functioning properly, and I suspect these errors may be the reason. However, I am unsure of their significan ...

What steps should I take in order to correctly implement the onChange event and retrieve the event.target.value in my

Incorporating useForm, yupResolver, and Yup for validation caused issues with the previously functioning handleChange function. The value variable doesn't log anything when console.logged, indicating a disconnect with the input field content. Addition ...

Error in Typescript: The property 'children' is not included in the type but is necessary in the 'CommonProps' type definition

Encountering this error for the first time, so please bear with me. While working on a project, I opened a file to make a change. However, instead of actually making any changes, I simply formatted the file using Prettier. Immediately after formatting, t ...

Angular 2's latest release, RC.5, introduces an indispensable singleton global shared

I am currently working on implementing global singleton services. I came across this solution - https://angular.io/docs/ts/latest/guide/ngmodule.html#!#shared-module, but unfortunately it is not working for me. Here's a simplified version of my share ...

Fade-in and fade-out animations in Angular triggered by a click event

I developed a fade-in, fade-out animation for a div element. My goal is to achieve the following: Upon initial page load, there is a div element that displays some numbers. On the right and left sides of the div, there are two buttons. When a user cl ...

AngularJS ng-model not refreshing

One of the features in my application is a Font Awesome icon picker that allows employees to easily access different icons without having to search for their codes online. However, I am facing an issue where clicking on an icon does not update the ng-mode ...

Type verification not functioning properly in a standalone TypeScript function

I am trying to validate the type of a parameter in a separate function, but I keep getting this error: Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable ...

incorrect indexing in ordered list

I am facing an issue with the ngIf directive in Angular. My objective is to create a notification system that alerts users about any missing fields. Here's a stackblitz example showcasing the problem: https://stackblitz.com/edit/angular-behnqj To re ...

Encountered an issue launching the advanced web server and reverse proxy server nginx for high performance

UPDATE - Recently, I encountered the following error logs: nginx: [emerg] unknown "request_url" variable Aug 19 01:14:58 nginx[4890]: nginx: configuration file /etc/nginx/nginx.conf test failed Below is my nginx.conf file: user www-data; worker ...

Retrieving an individual instance of a component

Is there a way to access a specific instance of a component within an app that uses it multiple times in other components? Currently, when I use the query command "fixture.debugElement.query(By.directive(ComponentName)).componentInstance;", it only recogni ...

Reusing Ionic headers across multiple pages

I'm looking to reuse my HTML header across different pages within an Ionic 4 app. Here is a snippet of my code: header.html <ion-view> <ion-grid> <ion-row> <ion-col col-6 class="font"> < ...

Arranging a 2D array of matchups to ensure an equal distribution of home and away matches for each team

I am in the process of developing a unique UEFA Champions League 24 'Swiss Model' tournament with 36 teams. Each team is set to compete against 8 different opponents, resulting in a total of 144 matches. I already have a list of matchups prepared ...

Enhance constructor functionality in Ionic 4 by incorporating additional parameters

Recently, I started using Ionic and came across a location page. In the location/location.page.ts file, there was an automatically generated empty constructor like this: constructor() { } Initially, the page functioned properly with this setup. However, ...

Issue: MUI Autocomplete and react-hook-form failing to show the chosen option when using retrieved information

The MUI Autocomplete within a form built using react hook form is causing an issue. While filling out the form, everything works as expected. However, when trying to display the form with pre-fetched data, the Autocomplete only shows the selected option af ...

Using the concat operator along with the if statement in Angular to make sequential requests based on certain conditions

Managing multiple HTTP requests in a specific order is crucial for my event. To achieve this, I am utilizing the concat operator from rxjs. For instance, upon receiving data from the first request, I update local variables accordingly and proceed to the ne ...

Group multiple typescript files into separate outFile modules

Can TypeScript files be grouped into multiple outFiles? I want to bundle my Typescript code, but instead of one single JS file, I would like to organize my TS into separate JS files such as controllers.js and plugins.js. The options in the TypeScript pro ...

unable to retrieve JSON sub-elements

I encountered an issue while attempting to iterate through the JSON object provided. When trying to access the content-items using page.content-items, I received an error message. Is it possible to access an object that has a key with "-" in its name? Co ...

Using TypeScript generics to constrain to either a number or a string

I am working on coding a react input component that accepts a defaultValue parameter of type string | number. This component has a state type matching the type of the received defaultValue; This is my code: type TypeName<T> = T extends number ? "nu ...