最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Component template variable not updating when service emits a change (angular) - Stack Overflow

programmeradmin1浏览0评论

I have a service:

@Injectable({ providedIn: 'root' })
export class AuthenticationService {
  signInChange: Subject<boolean> = new Subject<boolean>();
  isSignedIn: boolean;

  constructor() {
    this.isSignedIn = false;
  }

  signInChange: Subject<boolean> = new Subject<boolean>();
  isSignedIn: boolean;

  login() {
    this.auth2.signIn()
      .then(user => {
        this.isSignedIn = true;
        this.signInChange.next(this.isSignedIn)
      })
      .catch(error => {
        console.log("Error signing in")
      })
  }

  logout() {
    this.auth2.signOut()
      .then(user => {
        this.isSignedIn = false;
        this.signInChange.next(this.isSignedIn)
      })
      .catch(error => {
        console.log("Error signing out")
      })
  }

and a ponent:

export class HomeComponent implements OnInit {
  signInSubscription: Subscription;
  isSignedIn: any;

  constructor(private authService: AuthenticationService) {
    this.isSignedIn = authService.isSignedIn;
    this.signInSubscription = authService.signInChange.subscribe(value => {
      console.log("status changed to: " + value)
      this.isSignedIn = value
    })
  }

  checkValues() {
    console.log("Component says: " + this.isSignedIn);
    console.log("Auth says: " + this.authService.isSignedIn)
  }

and here is the HTML:

<div id = "login-test">
  <div class="g-signin2"></div>
  <button (click)="signIn()">Sign in</button>
  <button (click)="signOut()">Sign out</button>
  <button (click)="checkValues()">Check values</button>
  <p>{{this.isSignedIn}}</p>
</div>

So the observable works as expected (eg. when the sign in status is change the correct status is logged) BUT on the template itself the variable does not update when a change is observed.

Here's what I dont understand:

  1. When I click the Check Values button, the output is ALWAYS correct. The isSignedIn property is being set correctly every time there is an update in the service. BUT THE TEMPLATE ITSELF DOESN'T UPDATE.

  2. If I set up a button to only toggle the value {{this.isSignedIn}}, the template updates real time. Why will it not update real time if the change is ing from the observable?!?

I have a service:

@Injectable({ providedIn: 'root' })
export class AuthenticationService {
  signInChange: Subject<boolean> = new Subject<boolean>();
  isSignedIn: boolean;

  constructor() {
    this.isSignedIn = false;
  }

  signInChange: Subject<boolean> = new Subject<boolean>();
  isSignedIn: boolean;

  login() {
    this.auth2.signIn()
      .then(user => {
        this.isSignedIn = true;
        this.signInChange.next(this.isSignedIn)
      })
      .catch(error => {
        console.log("Error signing in")
      })
  }

  logout() {
    this.auth2.signOut()
      .then(user => {
        this.isSignedIn = false;
        this.signInChange.next(this.isSignedIn)
      })
      .catch(error => {
        console.log("Error signing out")
      })
  }

and a ponent:

export class HomeComponent implements OnInit {
  signInSubscription: Subscription;
  isSignedIn: any;

  constructor(private authService: AuthenticationService) {
    this.isSignedIn = authService.isSignedIn;
    this.signInSubscription = authService.signInChange.subscribe(value => {
      console.log("status changed to: " + value)
      this.isSignedIn = value
    })
  }

  checkValues() {
    console.log("Component says: " + this.isSignedIn);
    console.log("Auth says: " + this.authService.isSignedIn)
  }

and here is the HTML:

<div id = "login-test">
  <div class="g-signin2"></div>
  <button (click)="signIn()">Sign in</button>
  <button (click)="signOut()">Sign out</button>
  <button (click)="checkValues()">Check values</button>
  <p>{{this.isSignedIn}}</p>
</div>

So the observable works as expected (eg. when the sign in status is change the correct status is logged) BUT on the template itself the variable does not update when a change is observed.

Here's what I dont understand:

  1. When I click the Check Values button, the output is ALWAYS correct. The isSignedIn property is being set correctly every time there is an update in the service. BUT THE TEMPLATE ITSELF DOESN'T UPDATE.

  2. If I set up a button to only toggle the value {{this.isSignedIn}}, the template updates real time. Why will it not update real time if the change is ing from the observable?!?

Share Improve this question edited Mar 18, 2020 at 23:29 Jake Chambers asked Mar 18, 2020 at 23:00 Jake ChambersJake Chambers 5632 gold badges8 silver badges25 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 5

Because the variable isSignedIn in HomeComponent is assigned once in it's constructor and never re-assigned. And you are on the right path setting up an observable in the service. When you need the up-to-date value in ponent, use only the observable and do not use the boolean flag from the service directly.

Do the following in the ponent. Move the assignment inside the subscription and avoid using the boolean flag from the service directly.

import { Component, ngOnInit, ChangeDetectorRef } from '@angular/core';

export class HomeComponent implements OnInit {
  signInSubscription: Subscription;
  isSignedIn: any;

  constructor(private authService: AuthenticationService, private changeDetectorRef: ChangeDetectorRef) {
    this.isSignedIn = authService.isSignedIn;
    this.signInSubscription = authService.signInChange.subscribe(value => {
      console.log("status changed to: " + value)
      this.isSignedIn = value;
      this.changeDetectorRef.detectChanges();
    })
  }

  checkValues() {
    console.log("Component says: " + this.isSignedIn);
    console.log("Auth says: " + this.authService.isSignedIn)
  }
}

Edit - include ChangeDetectorRef

发布评论

评论列表(0)

  1. 暂无评论