Struggling to transfer array data from service to component

I am currently working on passing an array from service.ts to a component. My goal is to display the array elements in a dialog box. However, I encountered a Typescript error

TypeError: Cannot read property 'departmentArr' of undefined
.

I am struggling to comprehend why departmentArr is being identified as undefined.

Within the service:

private todos: Todo[] = [];
private db: any;
public departmentArr: any = [];
    
async searchDepartments(): Promise<Observable<any>> {
  const fetchData3 = await this.db.todos.orderBy('department').keys(function (departments) {
    alert("Departments are: " + departments.join(','));
    this.departmentArr.push(departments.join(','));
  });
  return this.departmentArr;
}

In the Component, I am attempting to retrieve the array from departmentArr.

connection: any;
async showTable() {
    this.connection = (await this.todoService.searchDepartments()).subscribe(message => {
    //the message here signifies the array                     
    console.log(message);
    this.dialog.open(AppComponent, {
      disableClose: true,
      autoFocus: true,
      data: message
    });
  });
}

Where could my mistake lie?

Answer №1

Understanding the functionality of the this keyword in JavaScript is essential.

When passing a callback function to keys, the assumption that this points to the instance of the enclosing class is incorrect.

In function context under strict mode, this evaluates to undefined.

Potential solutions include:

  • Utilizing an arrow function. In arrow functions, this retains the value of the enclosing lexical context's this
  • Using a helper variable outside the callback that can be captured via the callback's lexical context
  • Modifying this behavior by utilizing the bind method

An illustrative example to demonstrate these concepts:

class MyClass {

public departmentArr: string[] = [];

 runCallback(fun: () => void) {
   fun();
 }

 searchDepartmentsFun() {
  this.runCallback(function() {
    console.log("In function: this: ", this);
  });
 }

 searchDepartmentsArrow() {
  this.runCallback(() => {
    console.log("In arrow function: this: ", this);
  });
 }

 searchDepartmentsCapture() {
  const capturedArr = this.departmentArr; 
  this.runCallback(function() {
    console.log("In fun with capture function: this: ", this, ' captured arr: ', capturedArr);
  });
 }

 searchDepartmentsBind() {
  this.runCallback(function() {
    console.log("In bound fun with capture function: this: ", this);
  }.bind(this));
 }


}

const c = new MyClass();
c.searchDepartmentsFun();
c.searchDepartmentsArrow();
c.searchDepartmentsCapture();
c.searchDepartmentsBind();

Link to Playground

Additionally, it may be beneficial to enable the noImplicitThis option to prevent any conflicts where this could shadow an outer value of 'this'. Since the solution involving bind is affected by this setting, it is less common in TypeScript.

Answer №2

I made a modification here by switching the function to an arrow function () =>


private todos: Todo[] = [];
private db: any;
public departmentArr: any = [];
    
async fetchDepartments(): Promise<Observable<any>> {
  const fetchData3 = await this.db.todos.orderBy('department').keys( (departments) => {
    alert("List of Departments: " + departments.join(','));
    this.departmentArr.push(departments.join(','));
  });
  return this.departmentArr;
}

Alternatively, you can create a local variable and assign this.departmentArr to it.

private todos: Todo[] = [];
private db: any;
public departmentArr: any = [];

async fetchDepartments(): Promise<Observable<any>> {
 var tempArr = this.departmentArr;
  const fetchData3 = await this.db.todos.orderBy('department').keys( (departments) => {
    alert("List of Departments: " + departments.join(','));
    tempArr.push(departments.join(','));
  });
  return tempArr;
}

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

Exploring the nested component structure in Angular4 (RC5)

Stepping into the world of Angular and stumbling upon an outdated tutorial meant for Angular 2 (yeah, I know). Angular4: @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent , MyChildComponent ], bootstrap: [ AppComponent ] }) It a ...

"An issue occurred while trying to utilize the output received from the angular service (undefined

I currently have two variables declared in my Typescript class: private myServiceSubscription: Subscription; myVar: myDto[] = []; Within the constructor: this.myServiceSubscription = this.deliveryPointService .getPostalAddresses() .subsc ...

Bringing Angular ECharts into a Stackblitz 15.1 setup: A How-To Guide

Recently, Stackblitz made a change to use a standalone configuration for Angular Projects. However, when trying to initialize the module for Angular ECharts (ngx-echarts), an error occurred: Error in src/main.ts (18:5) Type 'ModuleWithProviders<Ngx ...

Empty results in NgRx Parameterized Selector

Having trouble implementing a parameterized query in NgRx and receiving empty results. Check out the StackBlitz version of the code here: https://stackblitz.com/edit/ngrx-parameterized-query Update to Reducer Code export const userAdapter = createEntity ...

Resolve routing problems with lazy loading in Angular7

I have been working on implementing lazy loading in my Angular project. However, I am encountering the same error even after following the suggested solution. Lazy loading error on StackOverflow I have exported the components from the project module and im ...

What is the best approach to obtain complete and error methods from the server using BehaviorSubject?

Here is a description of my unique service: @Injectable() export class SettingService { private settings = new BehaviorSubject<any[]>([]); constructor(private http: HttpClient) { this.loadSettings(); } private loadSettings( ...

Is there a way to extract the HTMLElement[] type from the DOM?

In my TypeScript project, I am trying to gather all the top-level elements of a page using the code snippet below: const getHTMLElement() : HTMLElement[] { const doc = document.body.children; const list : HTMLElement[] = []; for (let c of Array.f ...

Organizing a store in a hierarchical structure

I am currently facing an issue with creating a hierarchical store in Angular. My goal is to have multiple reducers that work on specific parts of the application. Here's the scenario: I am working on an HR application that has a talent (employee) mod ...

There was an issue converting the value {null} to the data type 'System.Int32', resulting in a 400 error

Attempting to make a POST request with some missing data is causing errors in my angular form. Here is the payload I am using: DeviceDetail{ deviceId:'332', sideId: null, deviceName:'test' } Unfortunately, I encountered a 400 bad re ...

Attempting to retrieve JSON data and present it in a grid layout

I have a JSON file with the following data: { "rooms":[ { "id": "1", "name": "living", "Description": "The living room", "backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz7 ...

Issues arise when attempting to override attributes within the HTML of a parent component in Angular

Why does overriding an attribute in a child class that extends from another not work as expected? Here's a made-up scenario to simplify the issue: Parent class file: gridbase.component.ts import { Component, OnInit } from '@angular/core'; ...

The null error occurs when rendering with React's state array

When I try to call an API that emits JSON, I am encountering an issue. I call the promise API function in componentDidMount, set the state, and then call it in the render method, but it always returns a null error. I need assistance, please. Interface fo ...

Advantages of Using Constructor Parameter Initialization Over the new Keyword in Angular 5

Sample CODE 1 : import { Component,OnInit } from '@angular/core'; import {exampleClass} from './exampleClass' @Component({ selector: 'app-root', templateUrl: './app.component.html', styleU ...

What is the process for extracting the elements of an array fetched from a service in Angular 2?

Currently, I am learning Angular 2 + PrimeNG and going through a quick start project available at the following link: https://github.com/primefaces/primeng-quickstart The project is a CRUD application and it functions flawlessly. The data is neatly displa ...

Steps for converting a tsx file into a js file in React

Currently, I am in the process of a React Project and have numerous tsx files that I aim to convert for utilization as JavaScript within my project. What would be the best approach to achieve this task? ...

Improving my solution with PrimeNG in Angular2 - fixing the undefined tag error

After working with Angular for just three days, I successfully set up a login page dashboard using a web API solution. Everything was working great until I encountered an issue when trying to load the PrimeNG DataTableModule into my components. After searc ...

Discovering a specific property of an object within an array using Typescript

My task involves retrieving an employer's ID based on their name from a list of employers. The function below is used to fetch the list of employers from another API. getEmployers(): void { this.employersService.getEmployers().subscribe((employer ...

Checkbox offering a tri-state option

Seeking help on creating a checkbox with three states. I have implemented a method to toggle between these states upon clicking. However, the issue is that this method is only triggered after the HTML changes. As a result, the checkbox's navigation be ...

Multiple invocations of the callback function in an Angular5 template binding

In trying to create a grid component that uses structured data containing definitions for columns and an array of data. Each column definition includes a callback function to customize the display of that specific column's value. Within each callbac ...

What is the best way to include a router-link in a button click event in Angular 8?

Can someone please help me with adding a routing function to a button in Angular? I have already included a (click) function on the button, but how do I actually make the function navigate within the home.ts component? <button class="navbut" (click)= ...