Reputation: 8959
I have a ProfileImageComponent
that, when clicked, emits the user object it's associated with using my UserProfileService
service. See this code:
export class ProfileImageComponent {
@Input() user;
constructor(private userProfileService: UserProfileService, private sidebarService: SidebarService, private storageService: StorageService, private route: Router) { }
openUserProfile() {
// mobile
if(window.innerWidth < 768) {
this.route.navigate([`/user-profile/${this.user.pk}/`]);
this.userProfileService.openUserProfile('view', this.user);
} else {
// tablet and above
let loggedInUserPk = JSON.parse(this.storageService.getItem('User'))['pk'];
let action = this.user['pk'] === loggedInUserPk ? 'edit' : 'view';
if(!this.sidebarService.sidebarOpened) {
this.userProfileService.openUserProfile(action, this.user);
this.sidebarService.openSidebar();
} else {
this.sidebarService.closeSidebar();
}
}
}
Explanation of the above:
On mobile I have a specific route url for the user profile where I route to if the window is smaller than 768px. The line after the route emits an action and the user object associated.
On tablet and above we instead open a sidebar which doesn't require a route change - it emits the value and opens the sidebar.
The UserProfileComponent
that subscribes to the emitted value does receive the value regardless of screens. Here's its OnInit
:
ngOnInit() {
this.userProfileSubscription = this.userProfileService.userProfile$
.subscribe((profile) => {
this.canEditProfile = profile['action'] === 'edit' ? true : false;
this.user = profile['user'];
this.cdr.markForCheck();
});
}
In my HTML I just want to display the data at this stage:
<div id="user-profile">
<p>User : {{ user | json }}</p>
</div>
The problem: The data doesn't display on mobile unless I click twice, even though the data is definitely getting there and the model is being updated.
I tried to mark it for change detection but it didn't work (this.cdr.markForCheck();
)
I also tried adding the | async
pipe to the user object in the HTML but it didn't change either.
What am I doing wrong?
EDIT
The UserProfileService
:
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class UserProfileService {
private userProfileSource = new Subject<any>();
userProfile$ = this.userProfileSource.asObservable();
constructor() { }
openUserProfile(action, user) {
this.userProfileSource.next({ action: action, user: user });
}
}
Upvotes: 1
Views: 1245
Reputation: 7221
Router.navigate is asynchronous. The problem is probably that you emit your data (through this.userProfileService.openUserProfile('view', this.user)
before the OnInit
in UserProfileComponent
.
You can use a BehaviorSubject in your userProfileService
that will replay the last value emitted during the OnInit
.
Upvotes: 2