'one component not getting update when other component update from shared service with Observable Subject
I have 2 component, ProfileComponent and AvatarComponent with no direct relation between them
Profile Component is used under user module ( user.module.ts ) and avatar component is being used in main module ( app.module.ts ) where I display user full name and profile picture on right top side.
My requirement is Whenever user edit his/her profile ( first name or last name ) and hit save button. than avatar also getting updated with new first name and last name
I have followed this Component Communication approach from Angular Documentation
but my issue is that avatar is never being updated, even constructor is not being called from avatar.component.ts
angular version 4.3.4
following is the relevant code
Profile.component.ts
import { Component } from '@angular/core';
import { UserService } from '../user.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html'
})
export class ProfileComponent implements OnInit {
constructor(private userService: UserService) { }
announce() {
console.log('announce called: ');
let username = 'alpha beta';
this.userService.announceUser(username);
}
// when click on save button on edit profile button
updateProfile(userProfile) {
this.userService.updateUserDetail(userProfile).subscribe(
(data: any) => {
this.announce();
}
);
}
}
avatar.component.ts
import { Component, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { UserService } from '../../../user/user.service';
@Component({
selector: 'app-avatar',
templateUrl: `<div>
<img #avatar [title]="fullName" alt="profile-picture">
<span>{{fullName}}</span>
</div>`
})
export class AvatarComponent implements OnDestroy {
fullName: string;
subscription: Subscription;
constructor(private userService: UserService) {
this.getAvatar();
this.subscription = userService.missionAnnounced$.subscribe(
username => {
console.log('subscribe it in constructor'); //never being called
this.fullName = username;
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
getAvatar() {
this.userService.getUserDetail().subscribe(
(data) => {
this.fullName = `${data.firstName} ${data.lastName}`;
this.userService.getProfilePicture().subscribe(
(image) => {
this.image.nativeElement.src = window.URL.createObjectURL(image);
}
);
}
);
}
}
user.service.js
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class UserService {
private missionAnnounceUsername = new Subject<string>();
missionAnnounced$ = this.missionAnnounceUsername.asObservable();
constructor(private httpClient: HttpClient) { }
announceUser(user: string) {
console.log('announceUser: ', user);
this.missionAnnounceUsername.next(user);
}
getUserDetail() {
return this.httpClient.get(`/user/profile`).map((res) => res.item);
}
updateUserDetail(data) {
return this.httpClient.put(`/user/profile`, data);
}
}
Solution 1:[1]
found the solution from this issue
"Do not register any provider twice as this will create two independent instances."
I have registered UserService in main module app.module.ts whereas it should be in providers metadata of parent component of avatar.component.ts which is layout.component.ts
- removed
UserServicefrom app.module.ts providers metadata. - add
UserServicefrom layout.component.ts providers metadata.
as <app-avatar> is used in layout.component.html
everything is working fine now.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | diEcho |
