I'm working with Angular 16 for a project that involves using balkan family tree , but I got stuck with a problem in a service
This is the function where it emits the value, is using HttpClient from Angular Core:
this.httpClient.get(url, { headers }).subscribe(
{
next: res => {
console.log(res);
this.apiResponse = res;
this.cdr.detectChanges();
this.zone.run(()=>{
this.specimenData.$specimens.emit(res);
});
this.specimens = this.apiResponse;
},
error: err => {
console.log(err);
}
}
);
As you can see i tried to view the content of the response and its defined with the data i need to emit. I also tried to make Angular to detect the changes and do the emit action into the zone, but nothing works! I just got the undefined when i subscribe to the service in this function (this function is on another component):
this.specimenData.$specimens.subscribe(value => { this.data = value });
if (this.data != undefined) {
var specimens = [];
const tree = document.getElementById('tree');
if (tree) {
var family = new FamilyTree(tree, {
nodeBinding: {
field_0: "name",
img_0: "img"
},
});
family.load([
{ id: 1, pids: [2], name: "Amber McKenzie", gender: "female", img: "https://cdn.balkan.app/shared/2.jpg" },
{ id: 2, pids: [1], name: "Ava Field", gender: "male", img: "https://cdn.balkan.app/shared/m30/5.jpg" },
{ id: 3, mid: 1, fid: 2, name: "Peter Stevens", gender: "male", img: "https://cdn.balkan.app/shared/m10/2.jpg" },
{ id: 4, mid: 1, fid: 2, name: "Savin Stevens", gender: "male", img: "https://cdn.balkan.app/shared/m10/1.jpg" },
{ id: 5, mid: 1, fid: 2, name: "Emma Stevens", gender: "female", img: "https://cdn.balkan.app/shared/w10/3.jpg" }
]);
}
} else {
console.log("im showing from tree component"+this.data);
}
As you can see when i pass the value from the subscribe method for the service it passes an undefined and the console shows the message in the else way. Is weird because I´m using another services in my app and they are working fine, even some of them are emiting an api response like this one, this is the code for the service in his file:
import { EventEmitter, Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class SpecimensService {
constructor() { }
$specimens = new EventEmitter<any>();
}
I tried changing the 'Injectable' to 'inject' but didn't work, I also tried to add the service to the providers in NgModule but nothing, if someone have an idea or a clue of whats happening please tell me, if you need more info feel free to ask me for it.
A couple of observations that could fix your problem.
EventEmitteris used for communication between parent/child components not on services.If you are handling the application state in a service, use subjects (
Subject,BehaviorSubject,AsyncSubject,ReplaySubject) depending on the situation.You shouldn't
subscribetoobservablesin your service, there are some exceptions but try not to, instead, your service functions should return anobservableso any component can react to any changes that might happen in the service (by usingnext()).Avoid using
var, stick with eitherletorconstdepending on if the variable will be changed later.Use
Angularfor interacting with theDOM, don't use nativejavascript, you could make use ofViewChildSince you are using
Angular v16, you can make use oftakeUntilDestroyedfor handling the subscription if you need to subscribe to anobservablemanually.Given these suggestions, you could refactor your current code as the following:
service
component HTML
component