I'm creating a Facebook service that calls the Facebook javascript api and am wondering how to best implement change detection when my values are updated.
I have a UserService which has a currentUser property that is a BehaviorSubject:
currentUser: Subject<User> = new BehaviorSubject<User>(new User(null)); And when I want to update the user in response to the facebook javascript sdk telling me the user has logged in or logged out, I update that and need to call tick() on an ApplicationRef:
updateUser(user: User) { console.log('UserService.updateUser:', user); this.currentUser.next(user); this.appRef.tick(); // UI does not update without this } constructor(facebook: Facebook) { this.facebook.facebookEvents.filter(x => x != null && x.eventName == 'auth.authResponseChange') .subscribe((event) => { this.updateUser(new User(event.data)); } } In my component I store the 'currentUser' from the user service in the constructor and bind to the value property:
<h2>Logged into Facebook as {{currentUser.value.name}}</h2> <p>Is this you? <img src="{{currentUser.value.profilePicUrl}}"></p> Am I doing something wrong? Is there a better way than having to call ApplicationRef.tick() after a change triggered from an external library?
Edit
I tried using NgZone and that doesn't work, using a different event that returns posts in a feed as the service pages through them:
constructor(userService: UserService, private ref: ApplicationRef, private zone: NgZone) ... this.postsSubject.subscribe((post) => { this.zone.runOutsideAngular(() => { // doesn't do anything this.posts.push(post); console.log('postsSubject POST, count is ', this.posts.length); ref.tick(); // required to update bindings }); } The console shows the count incrementing, but the html binding {{posts.length}} is only updated if I add the ref.tick() call...
I think I saw somewhere that you can make available 'inputs' to any component from the top-level app component which might be the way to go for the logged in user, but not other calls like getting posts in a feed...
{{ (currentUser | async)?.value?.name}}.