programing

다른 구성 요소에서 업데이트할 때 서비스 변수 변경을 감지하려면 어떻게 해야 합니까?

css3 2023. 9. 2. 08:43

다른 구성 요소에서 업데이트할 때 서비스 변수 변경을 감지하려면 어떻게 해야 합니까?

서비스 변수에서 업데이트된 값을 가져오려고 합니다(isSidebarVisible) 다른 구성 요소에 의해 계속 업데이트됩니다(header클릭 이벤트 포함(toggleSidebar).

사이드 바.service.ts

import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';

@Injectable() 
export class SidebarService {
    isSidebarVisible: boolean;

    sidebarVisibilityChange: Subject<boolean> = new Subject<boolean>();

    constructor()  {
        this.isSidebarVisible = false;
    }

    toggleSidebarVisibilty() {
        this.isSidebarVisible = !this.isSidebarVisible
        this.sidebarVisibilityChange.next(this.isSidebarVisible);
    }
}

사이드바.구성 요소.ts

export class SidebarComponent implements OnInit {
    asideVisible: boolean;
    _asideSubscription: any;

    constructor(private sidebarService: SidebarService) {
        this.asideVisible = sidebarService.isSidebarVisible
        this._asideSubscription = sidebarService.sidebarVisibilityChange.subscribe((value) => {
            this.asideVisible = value
        })
    }
    
    ngOnInit() {
    }
}

header.component.ts(서비스 변수가 업데이트되는 위치)

export class HeaderComponent implements OnInit {
    isSidebarVisible: boolean;
    _subscription: any;

    constructor(private sidebarService: SidebarService) {
        this._subscription = sidebarService.sidebarVisibilityChange.subscribe((value) => {
            this.isSidebarVisible = value
        })
    }

    toggleSidebar() {
        this.sidebarService.toggleSidebarVisibilty()
    }

    ngOnInit() {

    }
}

서비스 변수 값의 변화를 확인할 수 있습니다.header.component.html언제{{ isSidebarVisible }}그러나 인sidebar.component.html항상 기본값을 인쇄하고 변경 내용을 듣지 않습니다.

이것을 고치는 것을 도와주세요.

구독을 서비스로 이동하면 두 구성 요소 모두 이 값에 액세스할 수 있습니다.값이 한 번만 필요하면 sidebar.component에서 했던 것처럼 직접 사용할 수 있습니다.이 값으로 업데이트해야 하는 경우 getter를 사용할 수 있습니다(예: header.component).

사이드 바.service.ts:

@Injectable() 
export class SidebarService {
    isSidebarVisible: boolean;

    sidebarVisibilityChange: Subject<boolean> = new Subject<boolean>();

    constructor()  {
        this.sidebarVisibilityChange.subscribe((value) => {
            this.isSidebarVisible = value
        });
    }

    toggleSidebarVisibility() {
        this.sidebarVisibilityChange.next(!this.isSidebarVisible);
    }
}

사이드바.구성 요소.ts

export class SidebarComponent {
    asideVisible: boolean;

    constructor(private sidebarService: SidebarService) {
        this.asideVisible = sidebarService.isSidebarVisible;
    }
}

header.component.ts

export class HeaderComponent {
    constructor(private sidebarService: SidebarService) { }

    get isSidebarVisible(): boolean {
        return this.sidebarService.isSidebarVisible;
    }

    toggleSidebar() {
        this.sidebarService.toggleSidebarVisibility()
    }
}

또한 두 구성 요소 모두에서 제목을 구독하고 값을 얻을 수 있습니다.

this.sidebarService.sidebarVisibilityChange.subscribe(value => {...});

주제에 대해 자세히 알고 싶다면 여기를 보세요.

@이셔우드가 저를 트랙에 올려주었습니다, 감사합니다!이것이 나의 상황과 가장 닮은 질문과 대답이었습니다.

저의 경우 AngularFire의 변경 사항을 수신하는 앱 전체 사용자 서비스가 있습니다.Auth(authState) 및 유효한 사용자가 있는 경우 이름, 이메일, 색상 등 사용자의 정보(/appusers/${user.id })가 포함된 해당 사용자의 AngularFirestore 문서에 대한 수신기를 설정합니다.userService에서 필요한 모든 페이지는 수신기이므로 해당 데이터를 라이브로 가져옵니다( .subscribe().

문제는 더 많은 데이터베이스 작업을 수행하기 전에 사용자 문서 준비(로그인 및 사용자 문서 가져오기)에 의존하는 페이지가 있다는 것입니다.딥 링크를 통해 내부 페이지로 바로 이동할 때 페이지는 사용자 문서가 준비되기 전에 데이터베이스 작업을 수행하려고 시도하여 오류/충돌로 이어집니다.

위의 @isherwoods 지침에 따라 앱 페이지에서 사용자 데이터가 준비될 때까지 기다렸다가 추가 데이터베이스 작업을 수행하는 방법은 다음과 같습니다.

user.service.ts

export class UserService {

userDocumentReady: boolean = false; // initial value is "userdoc is not ready"
userDocObserver: Subject<boolean> = new Subject<boolean>(); // observing that bool

constructor(
  public fireauth: AngularFireAuth,
  public afs: AngularFirestore,
) {

// watch variable
this.userDocObserver.subscribe(value => this.userDocumentReady = value);

this.fireauth.authState
  .subscribe(user => {
    if (user) {

      this.afs.doc(`/tooluser/${user.uid}`).snapshotChanges()
      .subscribe(usr => {
        if (usr.payload.data()) {
          console.log(`got user object from database:`, usr.payload.data());              
          this.currentUser = usr.payload.data();

          this.userDocObserver.next(true); // flip UserDocumentReady flag

my tools.page.ts

// this is a logged-in page of the app,
// accessible through deep link https://my.app.domain/mytools

export class UsersPage implements OnInit {

constructor(
  public userService: UserService,
) { }

ngOnInit() {
  if (this.userService.userDocumentReady) {
    console.log(`users: userdoc already here, no need to wait`);
    this.setupPageData();
    return;
  }

  // wait for userdoc before setting up page
  this.userService.userDocObserver.subscribe(docReady => {
    if (docReady){
      console.log(`mytools: user ready value ${docReady}. now setup page.`);
      this.setupPageData(); // this function does the database stuff that depends on the user data to be ready first
    }
  });
}

이 "나에게 효과"가 있고 행동은 일관성이 있는 것처럼 보입니다.브라우저 표시줄에 URL을 입력하면 이러한 직접 탐색이 발생하므로 개발 시에도 매우 유용합니다.그것을 기억하기 위해 이것을 쓰는 것 - 그리고 그것이 다른 사람들에게 유용할 수 있는지 누가 압니까?

이것은 나의 두 번째 이온 앱이기 때문에 만약 내 구조/설정에 심각한 문제가 있다면, 나는 이 솔루션에 대한 코멘트에 매우 관심이 있습니다 :)

편집: 이미 존재하는 경우 새 사용자 문서를 기다리지 않도록 mytools.page.ts에 체크 인을 추가했습니다.

언급URL : https://stackoverflow.com/questions/43159090/how-can-i-detect-service-variable-change-when-updated-from-another-component