Challenges with Angular observables

Struggling to make observables work has been quite the challenge for me lately.

My code now resembles a chaotic battleground rather than the organized structure it once was.

The dreaded "ERROR TypeError: Cannot read property 'map' of undefined" keeps haunting me.

I've been attempting to import JSON data (which succeeds), filter out the active members (which works), sort them alphabetically (which fails), and create a unique list based on the "team" column (also failing).

This is how my service looks:

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
//import 'rxjs/add/operator/catch';
//import 'rxjs/add/operator/map';
import { catchError, map, tap } from 'rxjs/operators';

import { Member } from '../class/member';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Injectable()
export class UserinfoService
{

    //constructor
    constructor(private http: HttpClient)
    {

    }

    //methods or services

    getMembers(): Observable<Member[]>
    {
    return this.http.get<Member[]>('http://datalocation.com/JsonData/api/teammembers');
    }
}

And here's the component:

import { Component, OnInit, Injectable } from '@angular/core';
import { UserinfoService } from '../services/userinfo.service';
import { Member } from '../class/member';
import { MatDialog } from '@angular/material';
import { MemberdialogComponent } from '../memberdialog/memberdialog.component';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';

// import 'rxjs/Rx'; // adds ALL RxJS statics & operators to Observable


// Statics
import 'rxjs/add/observable/throw';

// Operators
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/toPromise';



@Component({
  selector: 'app-teammembers',
  templateUrl: './teammembers.component.html',
  styleUrls: ['./teammembers.component.css']
})
export class TeammembersComponent implements OnInit
{

  //props
  teamMembers: any[];
  searchQuery: any = "";
  searchResults: any[] = this.teamMembers;
  teams: any[];
  selectedTeam: any;

  //constructor
  constructor(private userinfoService: UserinfoService, public dialog: MatDialog)
  {
    //getData
    userinfoService.getMembers().subscribe(teamMembers => this.teamMembers = teamMembers
.filter(member => member.isActive)
.sort((a, b) => a.lastName.localeCompare(b.lastName)));


    //put all information in results
    this.searchResults = this.teamMembers;

    //getTeams
    this.teams = this.teamMembers
    .map(item => item.team)
    .filter((value, index, self) => self.indexOf(value) === index)
  }

If anyone can offer some guidance, I would truly appreciate it. I had everything running smoothly when it was just a simple service, but as soon as I introduced observables, chaos ensued.

Answer №1

Executing the code within a subscription runs asynchronously.

An attempted use of this.teamsMembers.map occurs before the variable this.teamsMembers is initialized by the subscription.

To resolve this issue, move your

this.teams = this.teamsMembers.map...
code inside the subscribe lambda function.

Answer №2

When using userinfoService.getMembers(), we subscribe to the teamMembers array and assign it to this.teamMembers after filtering out inactive members and sorting by last name.

You already have access to the teamMembers array in the component variable, so there is no need for mapping later on. You can directly apply filters to the teamMembers array for further manipulation.

//getTeams
this.teams = this.teamMembers.filter((value, index, self) => self.indexOf(value) === index)

Answer №3

To properly initialize your array, make sure to move all the contents inside your subscribe function.

While it's common to handle this logic in ngOnInit instead of the constructor, let's focus on getting it working correctly for now.

Another approach is to do the following:

teamMembers: any[] = new Array();
This will ensure that your array is initialized properly and not left undefined.

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

Implementing experimental decorators and type reconciliation in TypeScript - A step-by-step guide

My basic component includes the following code snippet: import * as React from 'react'; import { withRouter, RouteComponentProps } from 'react-router-dom'; export interface Props { }; @withRouter export default class Movies extends R ...

Is the 'Auto' option supported for the display property of Axes in Angular using Ng2-Charts?

Utilizing ng2-charts and chart.js in an Angular project for a line chart, I have defined the chart options as follows: I have set the display property to auto, ensuring that the y-axis is only displayed when there is data mapped to that axis. However, dur ...

The specified property cannot be found within the type 'JSX.IntrinsicElements'. TS2339

Out of the blue, my TypeScript is throwing an error every time I attempt to use header tags in my TSX files. The error message reads: Property 'h1' does not exist on type 'JSX.IntrinsicElements'. TS2339 It seems to accept all other ta ...

Unable to fix position: sticky issue following Angular 15 update

Following the angular material update to version 15, many of us experienced issues with CSS changes breaking. This also affected legacy code that included sticky headers. <div class="row"> <div class="col-12"> <di ...

Avoiding the use of reserved keywords as variable names in a model

I have been searching everywhere and can't find a solution to my unique issue. I am hoping someone can help me out as it would save me a lot of time and effort. The problem is that I need to use the variable name "new" in my Typescript class construct ...

Using Apache to rewrite wildcard subdomains for an Angular application

I am currently facing a challenge with my Angular app that needs to be set up under subdomains for multi-tenant support. Each subdomain represents a different tenant within the application. At present, I have an .htaccess configuration that successfully lo ...

A new Angular project has been created and saved at /.gitkeep

When attempting to create a new Angular project using the ng new command, the process begins but gets stuck at certain points. The creation of crm_ng/src/assets/.gitkeep (0 bytes) is completed successfully. However, while installing packages with npm, the ...

Issue with loading CSS in Angular 8 upon refreshing the page after building in production

Here is the structure of my index.html: <!doctype html> <html lang="hu"> <head> <meta charset="utf-8"> <title>WebsiteName</title> <base href="/"> <meta name="viewport& ...

Enhance Your NestJS Experience: Using Interceptors for Mapping and Error Handling

I'm looking for a NestJS interceptor that can log requests in all scenarios, including both successful executions and errors. Below is an example implementation: public intercept(context: ExecutionContext, next: CallHandler): Observable<any> { ...

Make the download window appear automatically when downloading a file

How can I use JavaScript/TypeScript to prompt the browser to open the download window? My goal is to give users the ability to rename the file and select the download folder, as most downloads are saved directly in the default location. This is how I curr ...

Set up a global variable for debugging

Looking to include and utilize the function below for debugging purposes: export function debug(string) { if(debugMode) { console.log(`DEBUG: ${string}`) } } However, I am unsure how to create a globally accessible variable like debugMode. Can this be ...

The requested resource does not have the 'Access-Control-Allow-Origin' header

Currently, I am working on an application that utilizes Angular for the client side and NodeJs for the backend. The application is being hosted with iis and iisnode. Recently, I implemented windows authentication to the application in order to track which ...

What is the best way to send data to a child component in Angular, including components that can be

There are two components in my project: the parent component and the child component, each with their own unique markup. It is crucial for this example that the child component fetches its own data to render and not be provided by the parent. Currently, th ...

Browser inspect tool is failing to hit breakpoints when using USB-connected device

While troubleshooting my Ionic Capacitor application on a USB connected device, I noticed that my browser dev-tools (Chrome, Edge, Firefox) are not hitting my breakpoints in the source code. Interestingly, when I run the application on ionic serve, everyt ...

Implementing a map display feature in Angular using search results

I need assistance with displaying a map in an Angular 2 application. I also want to be able to highlight specific locations or areas based on certain data points. For example: 1. Showing voting results on the map by highlighting different colored areas. ...

What is the proper way to call document methods, like getElementByID, in a tsx file?

I am currently in the process of converting plain JavaScript files to TypeScript within a React application. However, I am facing an error with document when using methods like document.getElementById("login-username"). Can you guide me on how to referen ...

Tips for handling promises in a class getter method in TypeScript

In two of my classes, I use async/await functions to retrieve products from the product class. export default class Products { async getProducts() : Promise<[]> { return await import('../data/products.json'); } } export defa ...

Determining the data type of an object key in Typescript

Is there a way to limit the indexed access type to only return the type of the key specified? interface User { id: string, name: string, age: number, token: string | null, } interface Updates<Schema> { set: Partial<Record< ...

Executing JavaScript functions externally from the Angular 6 application

I have a unique scenario where my angular 6 app is embedded within another application that injects JavaScript to the browser to expose specific functionalities to the angular app. For example, when running my angular app within this external application, ...

Is it possible to invoke Cucumber stepDefinitions from a separate project at the same directory level?

Currently, I have a project called integration_test that includes all test projects utilizing cucumberjs, typescript, and nodejs. Project1 contains the login implementation, and I would like to use this implementation in Scenarios from Project2 and Projec ...