Home > Software engineering >  ¿Why "this.memberSkills" is undefined?
¿Why "this.memberSkills" is undefined?

Time:01-15

I have a problem, when I call the groupSkillsByExpertise() function in ngOninit, I get a console.log that shows the property this.memberSkills as undefined. However, in the html template I can show the content of membersSkills. The goal is to filter in the groupSkillsByExpertise() function the array of memberSkills to show only the skills with expert level. But as I get memberSkills as undefined, I can't apply the filter.

This is 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"); */  
  } 
}

CodePudding user response:

Because you have a subscription setting your memberSkills in getMemberSkills, you will need to wait for that subscription to set the data before using it.

The data will be visible in the template because the change detection will update it when the data becomes available.

To make correct the order, you can either make the group of functions async, or, simply place the grouping function within the subscription, i.e:

  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();
        });
  }

CodePudding user response:

memberSkills will be undefined until it's affectation in the subscribe of findSkillsByMemberId that will happen asynchronously (so you don't know when it will get it's values)

You can probably initialize memberSkills when you declare it like this:

public memberSkills = new Array<Skill>();

So when you will try to do a filter, you will do it on an empty list instead of on a nothing.

You can also add the filter in the result of your subscribe, to filter the array exactly after you receive it.

CodePudding user response:

You can use this solution (convert obserbable to promise and add async/await):

 async getMemberSkills() {
    this.memberId = Number(this.activatedRoute.snapshot.paramMap.get('id'));
    return this.memberProfileService.findSkillsByMemberId(this.memberId).toPromise();
  }

  groupSkillsByExpertise() {
    this.memberSkills = await this.getMemberSkills();
    console.log(this.memberSkills);
  }
  •  Tags:  
  • Related