Angular 基于服务变量(由另一个组件设置)显示元素

Angular 基于服务变量(由另一个组件设置)显示元素,angular,angular7,Angular,Angular7,我有一个应用程序,试图在其中显示或隐藏基于服务中公共变量的元素。该变量的实例化类似于show:boolean=false但随后从子组件设置 我的问题是show似乎从未更新其值 在进行各种调试时,我发现show设置为其初始值,但一旦视图初始化完成,我的检查器显示show未定义,尽管这可能与我的问题无关 那么如何显示子组件中的父元素呢? 代码如下: app.component.html <div *ngIf="appService.show"> Loading </div>

我有一个应用程序,试图在其中显示或隐藏基于服务中公共变量的元素。该变量的实例化类似于
show:boolean=false但随后从子组件设置

我的问题是
show
似乎从未更新其值

在进行各种调试时,我发现
show
设置为其初始值,但一旦视图初始化完成,我的检查器显示
show
未定义,尽管这可能与我的问题无关

那么如何显示子组件中的父元素呢?

代码如下:

app.component.html

<div *ngIf="appService.show"> Loading </div>
<div *ngIf="!appService.show"> Content </div>
应用服务

export class AppService {

    public show: boolean = false;

    showLoader() {
        this.show = true;
    }

    hideLoader() {
        this.show = false;
    }
}
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AppService {

  public show$ = new BehaviorSubject(false);
  constructor() { }

  showLoader() {
    this.show$.next(true);
  }

  hideLoader() {
    this.show$.next(false);
  }
}
子组件

export class AppComponent implements OnInit {

    constructor(private appService: AppService) {}

    ngOnInit() {}
}
export class ChildComponent implements OnInit {

    constructor(private appService: AppService) {}

// This is just an example, I've got the showLoader() method firing after a subscription completes.
    ngOnInit(){
        this.appService.showLoader();
    }
}

使显示区域可见

应用服务

export class AppService {

    public show: boolean = false;

    showLoader() {
        this.show = true;
    }

    hideLoader() {
        this.show = false;
    }
}
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AppService {

  public show$ = new BehaviorSubject(false);
  constructor() { }

  showLoader() {
    this.show$.next(true);
  }

  hideLoader() {
    this.show$.next(false);
  }
}

并在任何需要收听的地方订阅

使显示区域可见

应用服务

export class AppService {

    public show: boolean = false;

    showLoader() {
        this.show = true;
    }

    hideLoader() {
        this.show = false;
    }
}
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AppService {

  public show$ = new BehaviorSubject(false);
  constructor() { }

  showLoader() {
    this.show$.next(true);
  }

  hideLoader() {
    this.show$.next(false);
  }
}

并在任何需要收听的地方订阅

实现这一点的最佳方法是创建一个可观察的对象来管理加载状态。我更喜欢使用
BehaviorSubject
,因为它会记住它发出的最后一个值。您可以让多个组件订阅加载服务。(更多关于行为主题)

这里是一个stackblitz的链接,我在这里实现了这个加载程序服务的一个简单版本:

编辑:我在答案中添加了
子组件的代码。我在stackblitz中有它,但忘了在这里添加它

主要注意事项:

loading.service.ts
有一个
BehaviorSubject
管理应用程序是否正在加载数据。它返回自身
.asObservable()
,因此没有子组件可以对其调用
.next()

export class LoadingService { 

  private _isLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);

  get isLoading$(): Observable<boolean> { 
     return this._isLoading$.asObservable();
  }

   // see the rest of the code in the stackblitz 
}
app.component.html

<ng-template [ngIf]="loadingService.isLoading$ | async" [ngIfElse]="loaded">
  Loading  
</ng-template>

<ng-template #loaded>
  Content has loaded
</ng-template>

<!-- see child.component -->
<child></child>
有关
ng模板的信息,请查看此资源:


对于
async
管道:

实现这一点的最佳方法是创建一个可观察对象来管理加载状态。我更喜欢使用
BehaviorSubject
,因为它会记住它发出的最后一个值。您可以让多个组件订阅加载服务。(更多关于行为主题)

这里是一个stackblitz的链接,我在这里实现了这个加载程序服务的一个简单版本:

编辑:我在答案中添加了
子组件的代码。我在stackblitz中有它,但忘了在这里添加它

主要注意事项:

loading.service.ts
有一个
BehaviorSubject
管理应用程序是否正在加载数据。它返回自身
.asObservable()
,因此没有子组件可以对其调用
.next()

export class LoadingService { 

  private _isLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);

  get isLoading$(): Observable<boolean> { 
     return this._isLoading$.asObservable();
  }

   // see the rest of the code in the stackblitz 
}
app.component.html

<ng-template [ngIf]="loadingService.isLoading$ | async" [ngIfElse]="loaded">
  Loading  
</ng-template>

<ng-template #loaded>
  Content has loaded
</ng-template>

<!-- see child.component -->
<child></child>
有关
ng模板的信息,请查看此资源:


对于
async
管道,这是一个:

所以我认为这是正确的方法,但是当我实现您的建议时,我得到了要显示的“加载”模板,但它从未达到加载状态,并不断显示“加载”模板。在我的index.html视图中,我使用插值显示静态标题,因此应该会显示一些内容。考虑到这一点,我应该能够订阅get isLoading$()方法,然后使用成功输出来确定加载是否完成,对吗?我实际上能够回答我自己的问题。我错过了在我的子组件中实际打开/关闭它的代码。干杯令人惊叹的!很高兴你让它工作了。很抱歉,我没有在我的答案中包含stackblitz代码中的所有代码。因此我认为这是正确的方法,但是当我实施您的建议时,我得到了要显示的“加载”模板,但它从未达到加载状态,并不断显示“加载”模板。在我的index.html视图中,我使用插值显示静态标题,因此应该会显示一些内容。考虑到这一点,我应该能够订阅get isLoading$()方法,然后使用成功输出来确定加载是否完成,对吗?我实际上能够回答我自己的问题。我错过了在我的子组件中实际打开/关闭它的代码。干杯令人惊叹的!很高兴你让它工作了。对不起,我没有在我的答案中包含我的stackblitz代码中的所有代码。