Unable to access data from Service during the OnInit lifecycle hook in Angular 2

In my code, I have a custom WorkingData object that is responsible for passing specific data between components. One of the properties in this object is today, which holds the current date as a Date object. My goal is to continuously update this property every second using a setInterval function. However, I'm encountering an issue where the workingData object is undefined at this point, resulting in the following console error:

Cannot set property 'today' of undefined

This problem occurs in the app.component.ts file:

import { Component, OnInit, AfterContentChecked } from '@angular/core';
import { WorkingData } from './services/working-data/working-data';
import { WorkingDataService } from './services/working-data/working-data.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [ WorkingDataService ]
})
export class AppComponent implements OnInit, AfterContentChecked {

  workingData: WorkingData;

  constructor(public _workingDataService: WorkingDataService) { }

  getWorkingData() {
    this._workingDataService.getWorkingData().then(workingData => this.workingData = workingData);
  }

  ngOnInit() {
    this.getWorkingData();
    console.log('OnInit()');
    console.log(this.workingData);           // doesn't work
    // setInterval(this.updateTime(), 1000); // doesn't work
  }
  ngAfterContentChecked() {
    console.log('AfterContentChecked()');
    console.log(this.workingData);           // doesn't work the first call but does after it is called again at some later point
    // setInterval(this.updateTime(), 1000); // doesn't work
  }
  updateTime() {
      this.workingData.today = new Date();
  }
}

The service file working-data.service.ts looks like this:

import {Injectable} from '@angular/core';
import {WorkingData} from './working-data';
import {WORKINGDATA} from './mock-working-data';

@Injectable()
export class WorkingDataService {
  getWorkingData(): Promise<WorkingData> {
    return Promise.resolve(WORKINGDATA);
  }
}

While the service seems to be functioning correctly when generating the view and logging data in the AfterContentChecked lifecycle hook, I'm unable to access the workingData object in the OnInit lifecycle hook. It appears that there might be an issue with how I'm utilizing the lifecycle hooks. How can I address this problem and initiate the setInterval immediately?

Answer №1

The use of observables is illustrated in this scenario. Promises and observables are both utilized for handling asynchronous operations that yield a single value.

When dealing with multiple values, observables are the preferred option as they are designed for this specific purpose.

import { Observable } from 'rxjs';
...
export class AppComponent {
  workingData$: Observable<WorkingData>;

  constructor(public _workingDataService: WorkingDataService) {
    this.workingData$ = Observable.interval(1000).startWith('initial value')
    .concatMapTo(Observable.fromPromise(_workingDataService.getWorkingData()))
    .do(data => data.today = new Date)

}

The result of workingData can be accessed using:

    this.workingData$.subscribe(data => this.workingData = data);

In most cases, this approach may seem unnecessary, as workingData$ can be subscribed to whenever required, and observables can be linked in the view using the async pipe:

{{ workingData$ | async }}

Answer №2

Attempting to modify the data before it is fully processed is not recommended. The function getWorkingData() operates asynchronously, meaning it returns a promise, not the actual data itself. It is advised to make any updates once the data has been successfully retrieved (within the callback function).

getWorkingData() {
  return this._workingDataService.getWorkingData();
}

ngOnInit() {
  this.getWorkingData().then(workingData => {
    this.workingData = workingData;
    // perform necessary actions here
    });
...
}

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

Hosting asynchronous bindings in Angular 2

I'm currently working on a component with the following code: @Component({ selector: 'my-selector', template: `<div>html code goes here</div> `, host: { '[style.background]': "'url(' ...

Identifying Labels for the Mean stack within a Database

In the process of developing a compact app using the MEAN stack (Mongo + Express.js + Angular4 + Node.js) for a basic application. Creating a database collection for users and here is an example record/document: { "firstName": "John", "lastName ...

Running your Angular application on a Node server: Step-by-step guide

I am looking to deploy my application using express on a Node server. This is the content of my server.js file: var express = require('express'); var path = require('path'); var app = express(); app.get('/', (req, res) => ...

Is NgForm considered a directive within Angular - is it a structural or attribute directive for components?

I'm new to this, so please bear with me. According to https://angular.io/guide/attribute-directives: Angular has three types of directives: Components – directives that come with a template. Structural directives – alter the DOM layout by adding ...

Detecting the check status of a checkbox in react native: a complete guide

I'm currently working on a scenario where I need to implement logic for checking or unchecking a checkbox in React Native. If the checkbox is checked, I want to print one string, and if it's unchecked, I want to print something else. How can I ac ...

The Angular router-outlet is refusing to display any content

I am new to Angular and currently learning through a lecture with hands-on practice. I have written the code below as instructed by my teacher, but it's not displaying anything on the screen. Can someone please assist me? app.module.ts : @NgModule({ ...

Troubleshooting: The issue of importing Angular 2 service in @NgModule

In my Angular 2 application, I have created an ExchangeService class that is decorated with @Injectable. This service is included in the main module of my application: @NgModule({ imports: [ BrowserModule, HttpModule, FormsModu ...

Issue encountered while attempting to package Azure project in Visual Studio 2015 Update1 due to difficulty copying Typescript files

Since upgrading to VS 2015 Update 1 (that includes Typescript 1.7) and Azure SDK 2.8, packaging my Azure application for deployment has become a challenge due to an error in the file path where the packager is attempting to copy the js output file: Erro ...

Navigating a relative path import to the correct `@types` in Typescript

When the browser runs, I require import * as d3 from '../lib/d3.js'; for d3 to be fetched correctly. I have confirmed that this does work as intended. However, the file that contains the above code, let's call it main.js, is generated from ...

Enhance the design of MDX in Next.js with a personalized layout

For my Next.js website, I aim to incorporate MDX and TypeScript-React pages. The goal is to have MDX pages automatically rendered with a default layout (such as applied styles, headers, footers) for ease of use by non-technical users when adding new pages. ...

Attempting to create a bar graph using Angular framework

I'm currently working on developing a dashboard in Angular that includes a chart feature. Within my Firebase Firestore database, I have two collections: 'mechanicQualifications' and 'mecanicos'. The 'mechanicQualifications&apo ...

Sort your list efficiently with a custom hook in React using Typescript

I've been working on developing a custom hook in React that sorts an array based on two arguments: the list itself and a string representing the key to sort by. Despite trying various approaches, I haven't been able to find a solution yet. I&apos ...

The error message TS2322 occurs due to the inability to assign the type 'Observable<{}[]>' to 'Observable<Archive[][]>'

While upgrading from Angular 5.2.11 to 7.3.9, I encountered a types issue that was not present in the previous version of Angular. After fixing the import for forkJoin, the code snippet below now throws an error: ERROR in src/app/reports/report-measureme ...

Files for the Express API and Sequelize are nowhere to be found

After collaborating with a Freelance developer for more than 10 months on a project, the developer suddenly disappeared without warning. Although he sent me a file containing the work he had completed, I realized that the backend API was missing. Project ...

Mastering unit testing with Behaviour Subjects in Angular

I am looking to test the get and set methods of my user.store.ts file. The get() method is used to retrieve users, while addUsers() is utilized to add new Users to the BehaviorSubject. How can I accomplish this? import { Injectable } from '@angular/c ...

Using Angular2 - How to pass the router parameter as a variable in ngForm

Struggling to pass a router param (id) to an ngForm and then to an event emitter. I am able to retrieve the id from the router successfully, but when trying to assign it to my singleOpenHome object, I encounter an undefined error: @Input() singleOpenHome: ...

The parent component is failing to pass the form values to the child form group in CVA

My Angular application (view source code on Stackblitz) is running Angular 15, and it utilizes reactive forms along with a ControlValueAccessor pattern to construct a parent form containing child form groups. However, I am encountering an issue where the d ...

Angular 17 doesn't seem to be correctly implementing *ngIf to hide the div

After spending hours trying to display a div based on certain conditions using *ngIf in Angular, I am still unable to make it work. The following code is not showing the expected result: <div *ngIf="item.billingItem=='Staff'">This ...

Oops! To access useCart functionality in your NextJS application, make sure to use it within a CartContextProvider

Encountering the error "useCart must be used within a CartContextProvider" in the NextJS application is causing some trouble. The useCart hook is being utilized from a custom useCart.tsx file, and a CartContextProvider is provided at the application's ...

Node C++ Addon Typescript declaration file

I have developed a Node C++ Addon that wraps a class similar to the one outlined in the official Node documentation. By using require(), I am able to access my addon and retrieve the constructor for my class in order to instantiate it. const { MyClass } = ...