Is the component loaded before NgOnInit completes its initialization process?

My component is making calls to a service that in turn calls an API. However, the component renders before these calls are completed, resulting in an empty page.

Here's the code snippet from the component:

import {Component, OnInit, OnDestroy} from '@angular/core';
import {AuthService} from '../services/auth.service';
import {AssignmentService} from '../services/assignment.service';
import {Assignment} from '../models/Assignment';
import {Request} from '../models/Request';
import {MeService} from '../services/me.service';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
import {Router} from '@angular/router';
import {NavbarService} from '../services/navbar.service';

@Component({
  selector: 'app-newrequest',
  templateUrl: './newrequest.component.html',
  providers: [AssignmentService]
})
export class NewrequestComponent implements OnInit {
  me: MicrosoftGraph.User;
  assignments: Assignment[];
  requests: Request[] = [];
  ready = false;

  constructor(private meService: MeService,
              private authService: AuthService,
              private assignmentService: AssignmentService,
              private router: Router,
              public nav: NavbarService) {
  }

  ngOnInit() {
    this.nav.show();
    this.nav.element = 'newrequests';
    if (localStorage.getItem('loggedin') === 'yes') {
      this.meService.getMe().subscribe(data => {
          this.me = data;
        },
        error => {
          console.log(error);
        },
        () => this.assignmentService.getAssignments().subscribe(data => {
            this.assignments = data;
          },
          error => {
            console.log(error);
          },
          () => {
            this.setRequests();
          }));
    } else {
      this.router.navigate(['']);
    }
  }

  onLogout() {
    this.authService.logout();
  }

  onLogin() {
    this.authService.login();
  }

  private setRequests() {
    this.assignments.forEach(item => {
      if (this.me.mail.toLowerCase() === item.lecturer.toLowerCase()) {
        this.parseRequests(item.request, item.name);
      }
    });

    this.ready = true;
  }

  private parseRequests(toSplit, name) {
    const split = toSplit.split(',');

    split.forEach(item => {
      this.requests.push(new Request(item, name));
    });
  }
}

This is the code snippet from the page:

<app-navbar-component></app-navbar-component>
<div *ngIf="ready">
  <div *ngFor="let request of requests">
    <p class="lead">{{request.user}}</p>
  </div>
</div>

This is the function within my service:

getAssignments() {
    return this.http.get(this.BASE_API_URL + '/assignments').catch(this.onError);
  }

I am not receiving any errors. The requests are being loaded successfully (confirmed via console.log). The only issue is that the page loads before the data finishes loading.

Any suggestions or ideas would be greatly appreciated!

Thank you in advance!

Answer №1

Have you attempted to utilize resolve?

Create a resolver and name it assignments-details.resolver.ts

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {MeService} from '../services/me.service';

@Injectable()
export class AssignmentsDetailsResolver implements Resolve<any> {

  constructor(api: MeService){}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
   return this.api.getAssignments();
  }

}

In your route configuration, implement the following structure

{
  path: 'your_path',
  component: NewrequestComponent,
  resolve: { AssignmentsDetails: AssignmentsDetailsResolver }
}

Ensure that in your NewrequestComponent, you import ActivatedRoute

import { ActivatedRoute } from '@angular/router'

Within your constructor, use it like this

 constructor(private meService: MeService,
              private authService: AuthService,
              private assignmentService: AssignmentService,
              private router: Router,
              public nav: NavbarService,
              private activateRoute: ActivatedRoute) {

   this.activateRoute.data.subscribe((response) => {
       //to get the response
       console.log(response.AssignmentsDetails);
     });
  }

Additionally, ensure that you register 'AssignmentsDetailsResolver' in the provider property of your module.

I hope this guidance proves helpful for you.

Answer №2

In the case of asynchronous service calls, data does not arrive immediately when subscribe is called.

If you don't set the 'ready' variable to true once the data arrives, you won't see any data on the page. Make sure to set it to true once the data is received:

this.me = data;
this.ready =true;

Alternatively, you can handle this through the safe navigation operator.

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

Facing problem retrieving iframe.contentWindow in Angular2 and encountering an issue when trying to call postMessage()

I currently have two separate projects - an Angular 2 project and a NodeJs project. Within my Angular 2 application, there is an iframe where I aim to display the content of the NodeJs app. My intention is to utilize the postMessage() method to establish c ...

Angular 2 Error: Unresolved Promise rejection - Unable to assign value to reference or variable

I'm currently working on an Ionic 2 app that includes a barcode reader feature. However, I encountered the following issue while trying to display data: Unhandled Promise rejection: Cannot assign to a reference or variable! ; Zone: ; Task: Promi ...

Error encountered while importing AgGridModule in Angular2: Unexpected token

I'm facing an issue while trying to integrate ag-grid into my Angular2 project. Whenever I include AgGridModule in the @NgModule imports, it triggers an error message: (SystemJS) Unexpected token at eval import { AgGridModule } from 'ag-grid-ang ...

The closeOnClickOutside feature seems to be malfunctioning in the angular-2-dropdown-multiselect plugin

I'm currently using 2 angular-2-dropdown-multiselect dropdowns within a bootstarp mega div. The issue I'm facing is that when I click on the dropdown, it opens fine. However, when I click outside of the dropdown, it doesn't close as expected ...

Eliminate special characters from a string using Protractor

I am currently in the process of writing protractor tests for my angular application. One particular test case that I am working on involves comparing a span value before and after clicking a button. it('Compare dollar values', function () { ...

Utilizing a Link element in conjunction with ListItem and Typescript for enhanced functionality

I am currently using material-ui version 3.5.1 My goal is to have ListItem utilize the Link component in the following manner: <ListItem component={Link} to="/some/path"> <ListItemText primary="Text" /> </ListItem> However, when I tr ...

When RouteProps is used to initialize useState, the state is not set

I am facing a dilemma with a component that utilizes useState. The state is initially set using a property from RouteComponentProps. Strangely, it functions correctly when I manually type the URL in the browser's address bar, but not when the URL is c ...

Typescript conditional filtering: unlocking the power of targeted searches

I'm attempting to dynamically filter an array based on user choices from multiple drop down menus. I want the filtering process to only consider the selected values from the drop downs and ignore any dropdown where a selection was not made. Is there a ...

Issues arising when routing ffmpeg to flac encoder

I am facing an issue with encoding a flac file with seektables. The ffmpeg's flac encoder does not include seektables, so I have to resort to using the flac Command Line Interface (CLI). My goal is to convert any arbitrary audio file into a seekable f ...

Displaying live, real-time information using ng-apexcharts

Is there a way to leverage the results of this loop: <div *ngFor="let hour of hours | async">{{ hour.messages }}</div> and incorporate it into the [series] of an Apex Chart? An attempt like this: <apx-chart *ngFor="let hour of hours | asyn ...

Function in Angular that provides the elementId when hovering over it

Currently, I am working on an angular project that involves creating a wiki window. Basically, when any element is hovered over with the mouse, its definition will appear inside the wiki window. I am wondering if it would be possible to create a global fun ...

Creating a OneToMany relationship in NestJS entity model

In my current project with NestJS, I am working on defining entity fields. While I have successfully defined a ManyToOne relation, I am facing difficulties in setting up the syntax for a OneToMany relation to match the structure of my other relationships. ...

Nativescript encountered an issue with ../node_modules/nativescript-plugin-firebase/firebase.js

I've been developing an app using Nativescript Angular and code sharing. Everything was working fine after upgrading to Angular 10 a few days ago. However, today I attempted to integrate Firebase using the nativescript-plugin-firebase plugin and encou ...

In React-Redux, attempting to assign a value to an empty string is not permitted

When using the useDispatch hook, I am facing an issue where I cannot set the string to an empty value. Instead, it always sets the value to the last character in the string. App.tsx const dispatch = useDispatch(); dispatch(updateLocation('')); ...

"Revolutionize your date and time selection with the dynamically updating columns

I am in need of a time selection feature where users can choose both hours and minutes. Each hour will have its own set of minutes, and the data structure should look like this: [ { hour: 1, minutes: [0, 15, 30], }, { hour: 4, minut ...

Tips for restricting a type field to a power of two within a type system

When looking at certain JavaScript code snippets, one may come across the following: function allocate(bits) { if ((bits & (bits - 1)) != 0) { throw "Parameter is not a power of 2"; } ... } In essence, there exists a restriction on ...

Formik glitch when select value does not update properly after making changes

In my TypeScript web app, I am using Formik 2.2.9 and encountering issues with the HTML select element. My form includes the following controls: export interface CriterionEdit { id: number; name: string; description: string; isDeleted: boo ...

Encountering issues with Phaser Sprite body when receiving undefined input

I am having trouble with flicking when I click the mouse. The variable on input.on is returning undefined when I click the mouse. Here is a code snippet that explains my issue. Phaser is a new concept to me. w : number; h : number; velocity:n ...

Reassigning Key Names and Types Based on Conditions

How can I modify object key names and properties in a way that allows existing keys and properties to remain the same or be modified (remapped)? My current approach does not properly handle mixed cases: export const FUNC_ENDING_HINT = "$func" as const; ty ...

Creating HTML elements dynamically based on the value of a prop within a React component

In my React component built using Typescript, it takes in three props: type, className, and children The main purpose of this component is to return an HTML element based on the value passed through type. Below is the code for the component: import React ...