Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement behavior subject using service in Angular 8

Tags:

I'm new to Angular and I'm having an issue.

I'm creating an app with several sibling components. When I update a value in one component other components don't update. I know that to resolve this issue I should use behaviour subject. But how do I implement it with my service, the components and all the templates?

Here is my code -

----------------------My service---------------------------

//import


@Injectable() 
export class CoachService {

    apiURL = environment.apiURL;

    constructor(private http: HttpClient ) { }

    coachProfile(token :string)
    {  
    return this.http.post<any>(this.apiURL+'/coach/profile_infos',{
      token: token
      })        
    }

    updateProfile(info: any, token: string, us_id: string) {
      return this.http.post<any[]>(this.apiURL + '/coach/update_profile', {
        token: token,
        us_id: us_id,
        us_lang: info.us_lang,
        us_firstname: info.us_firstname,
        us_lastname: info.us_lastname,
        us_sex: info.us_sex,
        us_birthdate: info.us_birthdate,
        us_national_number : info.us_national_number,
        us_email: info.us_email,
        us_gsm: info.us_gsm,        
        online_profile: info.online_profile,          
        us_address: info.us_address,
        us_zip: info.us_zip,
        us_city: info.us_city,
        country:{
          id: info.country.id
        }
        })

    } 

}

----------one component.ts-------------------

//import
//component decorator

export class CoordonneesComponent implements OnInit, OnDestroy {

private coachProfile;
  token: string = localStorage.getItem('token');
  us_id : string;
  us_lang: string; 
  infos_profile: any;
  online: any;


  constructor(private translate: TranslateService,private coachService: CoachService, private router: Router) { }

  ngOnInit() {

    this.coachProfile=this.coachService.coachProfile(this.token)
      .subscribe((data) => {
        this.infos_profile = data.results;
        this.online = this.infos_profile.online_profile;
        this.translate.use(this.infos_profile.us_lang)
        this.infos_profile.lang= this.infos_profile.us_lang;

      });

   .....
  }


updateCoordonees() {
  this.coachService.updateProfile(this.infos_profile, this.token, this.us_id)
    .subscribe((data: any) => {

      if(data.success && data.msg!=null)
      { 
  // do something
      }
      else
      {
       // do something
      }

    },
      (err) => {
        // do something
      });

}  



  ngOnDestroy() {
    this.countrieList.unsubscribe();
    this.coachProfile.unsubscribe();  
  }


}

like image 765
kkD97 Avatar asked Aug 05 '19 08:08

kkD97


People also ask

What is Behaviour service in Angular?

BehaviorSubject is both observer and type of observable. BehaviorSubject always need an initial/default value. Every observer on subscribe gets current value. Current value is either latest value emitted by source observable using next() method or initial/default value.

How do you develop a behavioral subject?

BehaviorSubject works in the following way: Create an internal subscriptions container. Set the current value kept by the subject to the initial value passed as an argument during instantiation. When a new subscription occurs, add it to the container and emit the current value to the corresponding observer.

How do you use subject observable in Angular 8?

A Subject is like an Observable but can multicast to many observers which means subject is at the same time an Observable and an Observer. A Subject is a Special type of Observable that allows value to be multicasted to many Observers. Subject are like event emitters.


2 Answers

I'm going to show you a simple way:

@Injectable() 
export class ProfileService {

    private profileObs$: BehaviorSubject<Profile> = new BehaviorSubject(null);

    getProfileObs(): Observable<Profile> {
        return this.profileObs$.asObservable();
    }

    setProfileObs(profile: Profile) {
        this.profileObs$.next(profile);
    }
}

Now when you update something anywhere in the application, you can set that change by the ProfileService and each subscriber is receiving the change. I recommend you subscribe in ngOnInit.

ngOnInit() {
  this.profileService.getProfileObs().subscribe(profile => this.profile = profile);
}

Never forget to unsubscribe from the observables to prevent memory leaks!

There are many ways u can do that --> Use a subscription and unsubscribe in ngOnDestroy() or use another subject and deliver it to takeUntil like this:

unsubscribe$: Subject<boolean> = new Subject();

...

ngOnInit() {    
  this.profileService.getProfileObs()
                     .pipe(takeUntil(this.unsubscribe$))
                     .subscribe(profile => this.profile = profile);
}

ngOnDestroy() {
  this.unsubscribe$.next(true);
  this.unsubscribe$.complete();
}
like image 104
sagat Avatar answered Oct 11 '22 13:10

sagat


First create a BehaviourSubject

this._source = new BehaviourSubject<yourType>(initialValue);
this.source = this._source.asObservable();

Define a function to "update" the BehaviourSubject

updateSource(newValue) {
    this._source.next(newValue)
}

Now subscribe in your components to the source

this.service.source.subscribe();

Note the behaviourSubject always needs an initial value and emits the last one

DOCS: https://www.learnrxjs.io/subjects/behaviorsubject.html

If you want to share the data from a httpRequest you should use shareReplay() operator instead, you can subscribe to the httpRequest from different components and the request will be made once and the data will be shared

DOCS: https://www.learnrxjs.io/operators/multicasting/sharereplay.html

like image 36
Robert garcia Avatar answered Oct 11 '22 11:10

Robert garcia