web-dev-qa-db-ja.com

Angular 8でサービスを使用して行動主体を実装する方法

Angularが初めてですが、問題が発生しています。

いくつかの兄弟コンポーネントを含むアプリを作成しています。 1つのコンポーネントの値を更新しても、他のコンポーネントが更新されません。この問題を解決するには、動作の件名を使用する必要があることを知っています。しかし、サービス、コンポーネント、およびすべてのテンプレートでどのように実装するのでしょうか。

これが私のコードです-

----------------------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();  
  }


}

2
kkD97

まずBehaviourSubjectを作成します

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

BehaviourSubjectを「更新」する関数を定義します

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

コンポーネントをソースにサブスクライブします

this.service.source.subscribe();

BehaviourSubjectは常に初期値を必要とし、最後の値を出力することに注意してください

文書: https://www.learnrxjs.io/subjects/behaviorsubject.html

HttpRequestからのデータを共有する場合は、代わりにshareReplay()演算子を使用する必要があります。別のコンポーネントからhttpRequestにサブスクライブすると、リクエストが1回行われ、データが共有されます。

ドキュメント: https://www.learnrxjs.io/operators/multicasting/sharereplay.html

0
Robert garcia

それにはいくつかの方法があります。ここではその1つについて説明します。

1)次のようにサービスを構築します。

// ReplaySubject is more flexible than BehaviorSubject, as it
// allows you to define how many past emissions should be available.
// But you can get an equivalent code with BehaviorSubject by
// coding like this:
// private _coachProfile$: BehaviorSubject<any | null> = 
//    new BehaviorSubject<any | null>(null);
private _coachProfile$: ReplaySubject<any> = new ReplaySubject<any>(1);

coachProfile(token :string)
{  
  return this.http.post<any>(this.apiURL+'/coach/profile_infos',{
    token: token,
  }).subscribe((profile) => this._coachProfile$.next(profile));        
}

subscribeToGetCoachProfile$()
{  
  return this._coachProfile$.asObservable();       
}

2)そしてあなたのコンポーネントで:

ngOnInit() {
  this.coachService.subscribeToGetCoachProfile$()
    .subscribe((profile) => this.coachProfile = profile);
}

考えられる方法は他にもありますが、質問に貼り付けたサンプルコードを考えると、これがより簡単な方法だと思います。

余談ですが、stackoverflowで検索を行うと、この質問(または同様の質問)がここで何度も尋ねられていることがわかります。たとえば、この他のアプローチで見てみましょう: 共通部分を再計算しない複数のサブスクリプション

0
julianobrasil

行動主体を使用して問題を解決する方法は次のとおりです。

@Injectable()
export class CoachService {
  apiURL = environment.apiURL;

  constructor(private http: HttpClient) { }

  updateProfile(info, token, us_id): Observable<any> {
    return Observable.create((behaviorSubject: BehaviorSubject<any>) => {
      const requestData = {
        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
        }
      };
      const url = [this.apiURL, '/coach/update_profile'].join('');

      return this.http.post(url, requestData).subscribe(
        data => {
          behaviorSubject.next(data);
        },
        err => {
          behaviorSubject.error(err);
          if (err && err.status === 401) {
            // Do some err handling
          }
        }
      );
    });
  }

}

ここで、データを投稿し、動作サブジェクトの結果をサブスクライブする場合、たとえば、ここにあるコンポーネントのに、単に次のようにします。

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

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

    },
      (err) => {
        // do some err handling
      });
} 

0
Malik M