What is the reason for the undefined value of "this.memberSkills"?

Encountering an issue when calling the groupSkillsByExpertise() function in ngOninit as the console.log displays this.memberSkills as undefined. However, the content of membersSkills can be displayed in the HTML template. The aim is to filter the array of memberSkills in the groupSkillsByExpertise() function to only show skills with expert level. Since memberSkills is undefined, the filter cannot be applied.

Below is the code from my member-profile-component.ts:

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { MemberContact } from 'src/app/models/member-contact/member-contact.interface';
import { MemberProfileService } from 'src/app/services/member-profile/member-profile.service';
import { Skill } from 'src/app/models/skill/skill.interface';
import { Language } from 'src/app/models/language/language.model';

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

  memberId: number;
  member: MemberContact;
  memberSkills: Array<Skill>;
  memberLanguages: Array<Language>;
  expertList: Array<Skill>;
  intermediateList: Array<Skill>;
  beginnerList: Array<Skill>;

  constructor(
    private activatedRoute: ActivatedRoute,
    private memberProfileService: MemberProfileService
  ) { }

  ngOnInit(): void {
      this.getMemberProfile();
      this.getMemberSkills();
      this.getMemberLanguages();
      this.groupSkillsByExpertise();
  }

  getMemberProfile() {
    this.memberId = Number(this.activatedRoute.snapshot.paramMap.get('id'));
    this.memberProfileService.findMemberById(this.memberId)
    .subscribe(member => this.member = member);
  }

  getMemberSkills() {
    this.memberId = Number(this.activatedRoute.snapshot.paramMap.get('id'));
    this.memberProfileService.findSkillsByMemberId(this.memberId)
    .subscribe(skills => this.memberSkills = skills);
  }

  getMemberLanguages() {
    this.memberId = Number(this.activatedRoute.snapshot.paramMap.get('id'));
    this.memberProfileService.findLanguageByMemberId(this.memberId)
    .subscribe(languages => this.memberLanguages = languages);
  }

  groupSkillsByExpertise() {
    console.log(this.memberSkills); // Why is this undefined?
    /* this.expertList = this.memberSkills.filter(skill => skill.skillLevel?.skillLevel === "Expert"); */  
  } 
}

Answer №1

Since you have a subscription setting your memberSkills in getMemberSkills, it is important to wait for that subscription to set the data before utilizing it.

The template will display the data as the change detection mechanism updates it when the necessary data is fetched.

To ensure the correct order of functions execution, you can either make the group of functions async or alternatively, include the grouping function within the subscription block like this:

  ngOnInit(): void {
      this.getMemberProfile();
      this.getMemberSkills();
      this.getMemberLanguages();
  }

  getMemberSkills() {
    this.memberId = Number(this.activatedRoute.snapshot.paramMap.get('id'));
    this.memberProfileService.findSkillsByMemberId(this.memberId)
    .subscribe(skills => {
            this.memberSkills = skills;
            this.groupSkillsByExpertise();
        });
  }

Answer №2

memberSkills will remain undefined until it is assigned a value in the subscribe function of findSkillsByMemberId. This assignment happens asynchronously, so the timing of when it receives its values is unknown.

To avoid dealing with an empty array, you can initialize memberSkills when declaring it like this:

public memberSkills = new Array<Skill>();

By initializing it with an empty array, you can perform filters on it without encountering any issues.

Additionally, you can add the filter directly to the result of the subscribe function to immediately filter the array once it is received.

Answer №3

If you want to streamline your code and utilize async/await, the following solution may be helpful:

 convertObservableToPromise = async () => {
    this.id = Number(this.route.snapshot.paramMap.get('id'));
    return this.skillProfileService.findSkillsByID(this.id).toPromise();
  }

  organizeSkillsByCategory = async () => {
    this.skills = await this.convertObservableToPromise();
    console.log(this.skills);
  }

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

Before the service call finishes, Akita queries this.selectAll and returns an empty list

Here is the code snippet from my file named widgetquery.ts: @Injectable({ providedIn: 'root' }) export class WidgetQuery extends QueryEntity<WidgetState, WidgetTO> { public Widget$: Observable<WidgetTO> = this.selectActive().filter( ...

When attempting to compile the building project following the upgrade to Angular 9, an error message is displayed stating "Unable to access property 'length' as it is undefined

I'm currently in the process of updating my Angular 9 project by following the migration guide on update.angular.io. After running ng update @angular/core @angular/cli, I encountered an error "ERROR in Cannot read property 'length' of undefi ...

There was a Runtime Error that occurred, stating a TypeError: It is not possible to access properties of an undefined value (specifically

I've encountered an issue with a donut chart implemented from react-apex charts. Every time I try to render the page containing the chart, an error occurs. However, if I make changes to a property of the chart, it renders without any errors on the fro ...

What is the proper way to retrieve a constant variable within a return statement?

Here is the code I have written: const keyToDisplayMessage = 'REGULAR_HOME'; const cf = format( { accountName: this.accountName, }, this.pageData.sucessMessages.keyToDisplayMessage, this.$route.name ); return cf; The ...

How can I dispatch multiple actions simultaneously within a single epic using redux-observable?

I am a newcomer to rxjs/redux observable and have two goals in mind: 1) enhance this epic to follow best practices 2) dispatch two actions from a single epic Many of the examples I've come across assume that the API library will throw an exception ...

Combining and linking 3 RxJS Observables in TypeScript and Angular 4 without nesting to achieve dependencies in the result

I have 3 observables that need to be chained together, with the result from the first one used in the other 2. They must run sequentially and each one should wait for the previous one to complete before starting. Is there a way to chain them without nestin ...

TypeScript focuses on checking the type of variables rather than their instance

Is there a way to pass a type (not an instance) as a parameter, with the condition that the type must be an extension of a specific base type? For example abstract class Shape { } class Circle extends Shape { } class Rectangle extends Shape { } class ...

Can you explain the purpose of the .json() function in Angular2?

Can you explain the purpose of the .json() function within http requests in Angular2? Here is an example code snippet: this.http.get('http://localhost:8080/getName') .subscribe(res => this.names = res.json()); Is it correct to assume that t ...

When receiving JSON and attempting to store the data in a variable, I encounter an issue where it returns the error message "undefined is not iterable (cannot read property Symbol

I'm currently integrating the Advice Slip API into my project. I am experiencing an issue when trying to store the JSON data in a variable like so: let advice; fetch("https://api.adviceslip.com/advice").then(response => response.json()). ...

Guide to properly defining the interface for JSON data in Angular6

component.ts import * as AssetId from "../../../assetid.json"; export class AssetID { abc: number; xxx: number; } export class Sample { public assetId: AssetID = AssetId; // Line no : 9 } assetid.json { "abc": 3, "xxx": 4 } Error ...

Sometimes the PDF does not display even though the iframe src attribute is updating in Angular 6

I have encountered an issue with displaying a PDF file in my code. Sometimes the PDF shows up correctly, but other times it fails to load. I even tried using an iFrame instead of embed but faced the same scenario. Can anyone provide assistance? Here is my ...

Angular reactive forms are experiencing a setback where the value of '[value]' is not being properly set for controls

My scenario is as follows: <input #physicalAddress1 type="text" formControlName="PhysicalAddressLine1" /> <tfg-toggle #physicalAsPostal formControlName="PhysicalAsPostal" [onText]="'Yes'" [offText ...

Where is the best place to obtain the clientSecret key for mounting Stripe elements?

UPDATED CODE Hello, I am looking to integrate Stripe for user subscriptions. I'm unsure about the client Secret key in my setup. I am using Ionic 5 with Angular 14 and Capacitor 5, along with PHP as the backend. In my implementation, I used PHP to ...

Executing asynchronous functions in Angular 2

In my Angular demo.ts file, I have included two functions fetchTables() and fetchAllTables() inside the constructor of a class. Both functions make API calls. However, I am facing an issue where one of the calls fails consistently. Sometimes fetchTables() ...

Angular 2 Return {responseBody: "assigned variable with [object Object]"}

In my Angular 2 application, I am encountering an issue where I am sending a variable from a service to a component. In the template, the variable appears as expected, however, when attempting to send this variable to a PHP script using POST, I receive [ ...

Utilize Angular to Transfer HTTP Array Data from a Service to a Component

As I work on developing an app with Angular, my current challenge involves a service that retrieves an Array of Data from an online source. My goal is to make this array accessible in other components but I'm facing difficulty in passing the data to t ...

The issue with Angular's two-way data binding in a string array is that it is not functioning properly

Can someone help me understand the correct way to use ng-model in an array of strings? I attempted the following: Component.ts toDos: string[] =["Todo1","Todo2","Todo3"]; Component.html <div *ngFor="let item of toDos;let index = index"> <i ...

Troubleshooting issue: How to effectively extract route params in Angular using switchMap

I've been following a tutorial on how to retrieve route parameters in the Angular Routing documentation. Initially, I successfully retrieved the route parameters using subscribe. this.getRouteParams$ = this.route.params.subscribe(params => { // ...

Typescript error: The argument containing 'username' and 'password' fields cannot be assigned to a parameter expecting only a 'string' type

My service is designed to take an endpoint and execute a HTTP call. Here is the code snippet: export const updatePassword = (data: { username: string; password: string; }): HttpResponse<string> => { const { usernam ...

If "return object[value1][value2] || default" does not work, it means that value1 is not a recognized property

Within my code, there is an object literal containing a method that retrieves a sub-property based on a specific input. If the lookup fails, it should return a default property. //private class, no export class TemplateSelection { 'bills'; & ...