Reputation: 83
I've been trying to get observable's working for a bit now, but i keep failing.
At this moment, my code is starting to look more like a battlefield then the order it normally used to be.
I keep getting the "ERROR TypeError: Cannot read property 'map' of undefined."
I am trying to import json data (which works), then filter out the members who are "Active" (which works), sort them alphabetically (which does not work) and get a unique list of everything that is in "team" column (which doesn't work).
The service looks as follows:
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');
}
}
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)
}
Any help would be greatly appreciated. I got everything working when it was just a service, but the moment that i started with observables, it got all messed up.
Upvotes: 0
Views: 583
Reputation: 7713
The code inside subscription is run asynchronously.
You are trying to do a this.teamsMembers.map
before this.teamsMembers is set by the subscription.
You should put your this.teams = this.teamsMembers.map...
code inside subscribe lambda function.
Upvotes: 3
Reputation: 114
You just need to move everything inside your subscribe.
Also not 100% on doing everything here in the constructor, I normally do this sort of thing in my ngOnInit but that's neither here nor there right now.
The other thing you can do is:
teamMembers: any[] = new Array();
This will actually initialise your array properly so that it isn't undefined.
Upvotes: 1
Reputation: 2820
userinfoService.getMembers().subscribe(teamMembers => this.teamMembers = teamMembers .filter(member => member.isActive) .sort((a, b) => a.lastName.localeCompare(b.lastName)));
Heare you have already got the teamMembers array in component variable. so no need to required map in the later part. you can directly use the filter on the teamMembers array.
//getTeams
this.teams = this.teamMembers.filter((value, index, self) => self.indexOf(value) === index)
Upvotes: 1