基于服务变量显示元素(由另一个组件设置)
Show element based on service variable (set by another component)
我有一个应用程序,我试图根据服务中的 public 变量显示或隐藏元素。此变量像 show: boolean = false;
一样实例化,但随后从子组件设置。
我的问题是 show
似乎永远不会更新它的值。
在进行各种调试时,我发现 show
设置为初始值,但是一旦视图初始化完成,我的检查器显示 show
未定义,尽管这可能不是与我的问题有关。
那么如何显示子组件的父元素?
代码如下:
app.component.html
<div *ngIf="appService.show"> Loading </div>
<div *ngIf="!appService.show"> Content </div>
app.component
export class AppComponent implements OnInit {
constructor(private appService: AppService) {}
ngOnInit() {}
}
app.service
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();
}
}
让秀场成为可观察的。
app.service
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
因为它会记住它发出的最后一个值。您可以让多个组件订阅加载服务。 (更多关于行为主题 here)。
这是一个 link 到 stackblitz,我在其中实现了此加载程序服务的简单版本:https://stackblitz.com/edit/angular-loading-service-subscribe
编辑:我将 child.component
的代码添加到答案中。我在 stackblitz 里有它,但忘了在这里添加它。
要点:
loading.service.ts
有一个 BehaviorSubject
来管理应用程序是否正在加载数据。它 returns 本身 .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
我有一个应用程序,我试图根据服务中的 public 变量显示或隐藏元素。此变量像 show: boolean = false;
一样实例化,但随后从子组件设置。
我的问题是 show
似乎永远不会更新它的值。
在进行各种调试时,我发现 show
设置为初始值,但是一旦视图初始化完成,我的检查器显示 show
未定义,尽管这可能不是与我的问题有关。
那么如何显示子组件的父元素?
代码如下:
app.component.html
<div *ngIf="appService.show"> Loading </div>
<div *ngIf="!appService.show"> Content </div>
app.component
export class AppComponent implements OnInit {
constructor(private appService: AppService) {}
ngOnInit() {}
}
app.service
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();
}
}
让秀场成为可观察的。
app.service
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
因为它会记住它发出的最后一个值。您可以让多个组件订阅加载服务。 (更多关于行为主题 here)。
这是一个 link 到 stackblitz,我在其中实现了此加载程序服务的简单版本:https://stackblitz.com/edit/angular-loading-service-subscribe
编辑:我将 child.component
的代码添加到答案中。我在 stackblitz 里有它,但忘了在这里添加它。
要点:
loading.service.ts
有一个 BehaviorSubject
来管理应用程序是否正在加载数据。它 returns 本身 .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