Gabriel Geelario
Gabriel Geelario

Reputation: 237

How to use Behaviorsubject to detect change

Good day everyone. Please I have a problem working with BehaviorSubject. I Am trying to use a behavior subject in a shared service that gets/updates user information. I want when a user data is updated, other components that subscribe to the shared service will be updated too.

Service.ts

  private userData= new BehaviorSubject<any>([]);
  data = this.userData.asObservable();


   customerData: any;


// this gets user data
getUserInfo(id){
  this.apiUrl = ` ${this.siteUrl}customers/${id}`;

  this.customerData = this.http.get(this.apiUrl);

   this.userData.next(this.customerData);
   return this.customerData;

}

//Update user data

updateCustomerData(id, customerDataUpdated){
  let headers = new HttpHeaders ({
    "Content-Type" : "application/json"
  });
  this.apiUrl = `${this.siteUrl}customers/${id}`;

  return new Promise((resolve, reject) => {
    this.http.put(this.apiUrl, customerDataUpdated, {headers} ).subscribe(
      response => {
        resolve(response);

        this.userData.next(this.customerData);

    },
    error => {
      resolve(error);

    }
    )
  });

Profile.ts

Please tell me how do I use the BehaviorSubject here, so that if there is any update on any component subscribe to the shared service, this component will also be updated . Thanks

 customerData: any;  



  constructor( private WC: Service){
   }

     ngOnInit() {
       // get authenticated user id
        this.isUserLoggedIn = localStorage.getItem('currentUserId');


         this.WC.getUserInfo(this.isUserLoggedIn).subscribe((data)=>{
          this.customerData = data;  
        });


      }

edit page

  // Update user info
  async updateMethod(){

    let loading = await this.loadingCtrl.create({
      message: 'Updating...'
     });

     loading.present();
    this.isUserLoggedIn = localStorage.getItem('currentUserId');

    let customerDataUpdated = {
      "first_name": `${this.user.first_name}`,
      "last_name": `${this.user.last_name}`,
      "email": `${this.user.email}`,
      "username": `${this.user.username}`,
      "billing": {
     //   "first_name": `${this.user.billing.phone}`,
     //   "last_name": `${this.user.value.billing_last_name}`,
        "address_1": `${this.user.billing.address_1}`,
      //  "address_2": `${this.user.value.billing_address_2}`,
      //  "postcode": `${this.user.value.billing_postcode}`,
      //  "email": `${this.user.value.billing_email}`,
       "phone": `${this.user.billing.phone}`
      },

    }


   console.log('new update', this.user);  
   //update user data
   this.WC.updateCustomerData(this.isUserLoggedIn, customerDataUpdated).then((data)=>{


    this.changedetector.detectChanges();
      loading.dismiss();  


     });  
  }


  }

Upvotes: 3

Views: 14934

Answers (2)

Shashank Vivek
Shashank Vivek

Reputation: 17504

Let me explain, You want to get getUserInfo depending on user ID which is http call. Hence it's triggered only once even though its an observable. Try:

service.ts

private userData= new BehaviorSubject<any>([]);
userInfo$ = this.userData.asObservable();

// this gets user data
getUserInfo(id){
  this.apiUrl = ` ${this.siteUrl}customers/${id}`;
  return this.http.get(this.apiUrl).pipe(switchMap(userData) => {
     this.userData$.next(userData);
     return this.userInfo$;
  }) 
}

private fetchUserInfo(id){
  this.apiUrl = ` ${this.siteUrl}customers/${id}`;
  this.http.get(this.apiUrl).subscriber(data =>{
    this.userData$.next(userData);
  })
}

//Update user data

updateCustomerData(id, customerDataUpdated){
  let headers = new HttpHeaders ({
    "Content-Type" : "application/json"
  });
  this.apiUrl = `${this.siteUrl}customers/${id}`;
  return this.http.put(this.apiUrl, customerDataUpdated, {headers}).pipe(
      tap(response => this.fetchUserInfo(id))
    )
  });

Make changes in edit-page.component.ts accordingly for updateCustomerData as it is not a promise anymore.

A note of caution: if you use userInfo$ and pass some other id into getUserInfo() then it'll affect your Profile.ts component. Because they are sharing common observable.

Upvotes: 2

Lasitha Narangoda
Lasitha Narangoda

Reputation: 141

Please try this,

customerData: any;  


constructor( private WC: Service){ }

ngOnInit() {
//this will triger when data is changing
this.WC.data.subcribe(res => {

});

}

Upvotes: 2

Related Questions