Observable is encountering an issue where the API service is becoming undefined

Here is a glimpse into my Angular 6 Ionic 4 app - the app.component.js file. I have set up an observable to call the API service every 2 minutes to check for new notifications. The first call goes through smoothly, but then I encounter an error stating

can't find listModel of undefined
, pointing towards my line
await this.api.listModel('Notification'
. Why does it suddenly become undefined? Any suggestions on how to resolve this issue?

...
import { LoadingService } from './loading.service';
import { apiService } from './...-api.service';
...

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  public appPages = [
    {
      title: 'Home',
      url: '/notifications',
      icon: 'notifications'
    },
  ...
  public title = 'Places';
  public addrKeys: string[];
  public addr: object;
  public hasUnactionedNotification: any = false;
  public notificationObservable: any;
  public account: any;
  public initials: any;

  constructor(
    private platform: Platform,
    private api: apiService,
    ...
  ) {
    this.initializeApp();
    this.initializeNotifAndInitials();
  }

  ...

  async initializeNotifAndInitials() {
    this.refreshNotifications();
    this.account = await this.accountService.getAccount();
    this.initials = this.account.firstName != null ? this.account.firstName.charAt(0) + this.account.lastName.charAt(0) : '';
    this.notificationObservable = interval(0.5 * 60 * 1000);
    this.notificationObservable.subscribe(this.refreshNotifications);
  }

  async refreshNotifications() {
    let notifications = await this.api.listModel('Notification', null, null, {
      page: 0,
      size: 15
    });
    this.hasUnactionedNotification = !!_.filter(notifications, {
      isActioned: false
    }).length;
    //boot out users who are no longer logged in
    this.account = await this.accountService.getAccount();
    if (!this.account) {
       this.router.navigateByUrl('/login');
    }
  }

}

Let's take a look at the structure of the API service call:

import { Injectable } from '@angular/core';
import { Observable, of, throwError } from 'rxjs';
import { HttpClient, HttpHeaders, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { catchError, tap, map } from 'rxjs/operators';
import { SessionService } from './session.service';
import { environment } from '../environments/environment';
import * as _ from 'lodash';
import * as moment from 'moment-timezone';

@Injectable({
  providedIn: 'root'
})
export class FinaeoApiService {
  pageSize: any = 20;

  constructor(
    private http: HttpClient,
    private sessionService: SessionService,
  ) { }

    async listModel(modelName, modelId, secondModelName, opts) {
    const options = await this.getRequestOptions();
    let params = <any> {
      page: _.get(opts, 'page', 0),
      size: _.get(opts, 'size', this.pageSize),
    };
    if (modelId === null && secondModelName === null) {
      params.disableCompany = _.get(opts, 'disableCompany', false);
    };
    if (!_.isEmpty(opts.filters)) {
      let filters = [];
      _.each(opts.filters, filter => {
        filters.push(`${filter.attribute},${filter.action}:${filter.value}`);
      });
      params.filter = filters.join(',');
    }
    if (!_.isEmpty(opts.sort)) {
      params.sort = opts.sort.join(',');
    }
    options.params = new HttpParams({
      fromObject: params
    });
    if (modelId === null && secondModelName === null) {
      return this.http.get(`${environment.apiUrl}/${modelName.toLowerCase()}`, options).toPromise().then(this.extractData).catch(this.handleError);
    } else {
      return this.http.get(`${environment.apiUrl}/${modelName.toLowerCase()}/${modelId}/${secondModelName.toLowerCase()}`, options).toPromise().then(this.extractData).catch(this.handleError);
    }
  }

https://i.sstatic.net/OzYkf.png

Answer №1

My suggestion to solve the issue is to utilize .bind(this)

For example:

this.notificationObservable.subscribe(this.refreshNotifications.bind(this));

However, I prefer a different syntax and would opt for

this.notificationObservable.subscribe(() => this.refreshNotifications());

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

How can you verify the data type of an object without resorting to type guarding

I have a situation where I need to deal with different types of objects. export interface A { links: number name: string } export interface B { cat: boolean name: string } Initially, I considered using this method: const IsTypeB = (obj: any): obj ...

In Typescript, is it possible to utilize the value from a particular key in a type declaration as the type for another key within the same declaration?

Consider a scenario where I am designing a Variable type that includes a key named type with a value of type string. Is there a method to extract the value from the type key and utilize it as the type for another key within the declaration, without resorti ...

Connecting Angular forms to retrieve form data using email

Hello, I am new to Angular and haven't had experience hosting a website before. I have created a contact form on my website and would like the form inputs to be sent to my email address whenever someone submits the form. Can anyone guide me on how to ...

What is the best way to retrieve class members using component properties?

I am looking to implement a mixin for setting the header and meta data in my project. I recently discovered vue-meta, which seems to work really well for this purpose. However, I am still getting acquainted with TypeScript and class-based components. How ...

The Docker setup for Angular 4 and Django has been successfully compiled, however the localhost:4200 is failing to load

I am looking to containerize an Angular 4 frontend with a Django backend and PostgreSQL database using Docker. Currently, my file structure is as follows. When I run docker-compose up, both the Angular 4 frontend and Django backend start successfully. Howe ...

Heroku is having trouble deploying an app that has both frontend and backend components merged together

I am currently facing an issue with my Angular frontend and Node.js backend app when deploying it to Heroku. The build and compile process is successful, but it seems that only the backend is running on Heroku when attempting to access the app. I have foll ...

Creating a layered image by drawing a shape over a photo in Ionic using canvas

While there are plenty of examples demonstrating how to draw on a canvas, my specific problem involves loading a photo into memory, adding a shape to exact coordinates over the photo, and then drawing/scaling the photo onto a canvas. I'm unsure of whe ...

Can TypeScript be used to dynamically render elements with props?

After extensive research on SO and the wider web, I'm struggling to find a solution. I have devised two components, Link and Button. In short, these act as wrappers for <a> and <button> elements with additional features like chevrons on t ...

Step-by-step guide on implementing a draggable component for selecting the year using React

I am looking to develop a draggable component in React without relying on any third-party library. Below, I have provided an image depicting how the component might look. Currently, my component code appears as follows: import React from 'react'; ...

Support for Chrome in Angular 8

Can someone please advise on the minimum version of Google Chrome that is supported by Angular 8? Additionally, I am looking for a way to prompt users to update their Chrome browser if it doesn't meet the required version. My Angular application seems ...

Show a component on click event in Angular 4

Looking for a solution to create an event on a button click that triggers another component? When clicked again, the component should be reduced with a part always remaining visible. While I am currently using [ngClass]='hidden' within the same c ...

Issue with accessing custom method in subclass in Typescript

Recently delving into TypeScript, I decided to subclass Error and add a new method called getCode() in my MyError class. export class MyError extends Error { public code: number; constructor(code: number, message?: string) { super(mes ...

Angular array: Cannot access property of undefined - Type Error

Having trouble fetching data from a web service? I keep encountering the same error message that says "ERROR TypeError: Cannot read property 'bu' of undefined", even though the data I want to show is appearing correctly. Check out the response an ...

Guide for integrating open-iconic into an Angular 2 project

After setting up my angular project and adding bootstrap to it, I realized that the latest version of bootstrap (version 4) does not include an icon library. In order to add icons, I decided to install open-iconic using this command: npm install open- ...

Implementing validation message upon editing an item in Angular8 - a step-by-step guide

When using reactive forms formArray to add a section of data, clicking on the Edit button will disable the Add New button. After editing and saving the data, the Add button is enabled again. However, if changes are made in the item while editing and then a ...

The implementation of TypeScript 3.5 resulted in a malfunction where the imported namespace was unable to locate the Enum during runtime

I recently upgraded an older Angular.js application from Typescript 2.7 to 3.5 and successfully compiled it using tsc.exe. During application runtime, I encountered an error message in certain parts of the code: TypeError: Cannot read property 'Enu ...

Is it necessary to transmit rule specifics to Stepfunctions?

Is it feasible to achieve what I'm attempting, or am I starting with an impossible task? When a Event Bridge Rule is triggered by an added event pattern, like shown below, should the detailed information be included in the step input? const rule = ne ...

Strange behavior in Angular 4 routing: Child module not rendering unless the page is manually refreshed

I've been trying to find a solution for this strange behavior but haven't had any success. There are no errors showing in either the Angular 4 console or the JavaScript console. Currently using Angular CLI (Angular 4). I'm encountering ...

Sending information from a Node server to an Ionic (AngularJS) client

I want to transfer data from an Ionic application to a Node server. Then, manipulate the data with Node and send the updated data back to Ionic. However, I am unsure of how to send the data back to Ionic. The client is using Ionic (AngularJS): $http({ ...

Struggling with the TypeScript generic syntax for the GroupBy function

Struggling to figure out where I'm going wrong with this TypeScript signature after spending some time on it. I've been working on a group by function: const group = <T>(items: T[], fn: (item: T) => T[keyof T]) => { return items.re ...