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

时间:2019-01-03 17:07:59

标签: angular angular7

我有一个应用程序,试图基于服务中的公共变量显示或隐藏元素。像show: boolean = false;一样实例化了此变量,但是随后从子组件中对其进行设置。

我的问题是show似乎从未更新过它的值。

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

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

以下代码:

app.component.html

<div *ngIf="appService.show"> Loading </div>
<div *ngIf="!appService.show"> Content </div>

应用组件

export class AppComponent implements OnInit {

    constructor(private appService: AppService) {}

    ngOnInit() {}
}

应用服务

export class AppService {

    public show: boolean = false;

    showLoader() {
        this.show = true;
    }

    hideLoader() {
        this.show = false;
    }
}

child.component

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

2 个答案:

答案 0 :(得分:1)

使显示字段可观察。

应用服务

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

并在需要收听的地方订阅。

答案 1 :(得分:1)

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

这是一个指向stackblitz的链接,在其中我实现了此加载程序服务的简单版本:https://stackblitz.com/edit/angular-loading-service-subscribe

编辑:我将child.component的代码添加到了答案中。我把它放在堆栈闪电战中,但是忘了在这里添加它。

主要说明:

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.ts

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
    // by making it public, you can subscribe in the template
    constructor(public loadingService: LoadingService) { }
}

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>

child.component然后可以使用loading.service控制加载指示器。

@Component({
  selector: 'child',
  template: `
    <h1>Child Component</h1>
    <button (click)="toggleLoading()">Change Loading</button>
  `,
  styles: [`h1 { font-family: Lato; }`]
})
export class ChildComponent {

  constructor(public loadingService: LoadingService) { }

  // simulates a 3 second load time for fetching data
  ngOnInit() {
    this.loadingService.startLoading();
    setTimeout(() => {
      this.loadingService.stopLoading();
    }, 3000);
  }

  // simple method to simulate user action that loads some new data
  toggleLoading(): void {
    this.loadingService.toggleLoading();
  }
}

签出此资源以获取有关ng-template的信息:https://toddmotto.com/angular-ngif-else-then

,其中一个用于async管道:https://angular.io/api/common/AsyncPipe