2
votes

I'm trying to make some components friendship. In AppComponent I get user pay balance in ngOnInit and subscribe for balance update. AppComponent is the root component. When user make a purchase in PaymentComponent, I want to set user pay balance in AppComponent. For these purposes I use BehaviorSubject in AuthService (singleton, import only in AppModule).

userInfo.getValue() in PaymentComponent is work, but in AppComponent subscribe() I don't receive any updates. What's the problem?

Thanks.

AppComponent

@Component({
  ...
  providers: []
})

export class AppComponent implements OnInit {
   
   public balance: number;   

   constructor(private authService: AuthService)  { }

   ngOnInit() {
      
      this.authService.getUserProfile();

      this.authService.userProfile.subscribe(
        (data) => { this.balance = data; },
        (error) => {console.log("error"); }
      );
   }

}

AuthService

@Injectable()
export class AuthService {

   public userInfo = new BehaviorSubject<Users>(null);
   public userProfile = this.userInfo.asObservable();

   getUserProfile() {
      this.http.get<Users>(Globals.base_url + 'profile').subscribe(
         data => { 
            this.userInfo.next(data);              
         },
         error => {  console.log(error); });
    }
}

PaymentComponent

@Component({
  ...
})
export class PaymentComponent implements OnInit {
   
   constructor(public authService:AuthService) { }

   ngOnInit() {
      this.http.post(Globals.base_url + 'balance_write_off', body).subscribe(
         data => { 
                   this.authService.userInfo.next(data);
                  //this.authService.userInfo.getValue();
                 },
         error => console.log("error", error)
      );
   }
}

UPDATE. Stackblitz: https://stackblitz.com/edit/angular-ivy-enelht?file=src/app/payment.component.ts

2
does this.http.post(Globals.base_url + 'balance_write_off', body) return anything ? Did you set a console log in your subscribe to see if it emits something ? - Quentin Fonck
Thank you for review. Yes, this.http.post(...) return actual balance info. console.log(this.authService.userInfo.next(data)) show me undefined. this.authService.userInfo.getValue() return me actual balance too. - Vola
a console.log of a next call will return nothing anyway. is your payement component and app component are initiated at the same time ? Do as @Lashan Fernando says, It should work better. Always define your subscription before emitting anything. - Quentin Fonck
AppComponent is root component in application. PaymentComponent initiated only when user makes a purchase. - Vola
Could you set your service @injectable decorator to @Injectable({providedIn: 'root'})` and remove it from your app.module providers to see if it changes anything ? - Quentin Fonck

2 Answers

0
votes

Swipe subscription in AppComponent

@Component({
  ...
  providers: []
})

export class AppComponent implements OnInit {
   
   public balance: number;   

   constructor(private authService: AuthService)  { }

   ngOnInit() {
      this.authService.userProfile.subscribe(
        (data) => { this.balance = data; },
        (error) => {console.log("error"); }
      );

      this.authService.getUserProfile();
   }

}
0
votes

There seems to be an issue with your data types.

@Injectable()
export class AuthService {
   public userInfo = new BehaviorSubject<Users>(null);
   public userProfile = this.userInfo.asObservable();

   getUserProfile() {
      this.http.get<Users>(Globals.base_url + 'profile').subscribe(
         data => this.userInfo.next(data),
         // other stuff
      )
    }
}

userProfiles Observable is of type Users

export class AppComponent implements OnInit {
   public balance: number;   

   constructor(private authService: AuthService)  { }

   ngOnInit() {
      this.authService.getUserProfile();

      this.authService.userProfile.subscribe(
        (data) => this.balance = data,
        // other stuff
      );
   }
}

Here you try to assign the data, which is of type Users, to type number, which won't work.