代码之家  ›  专栏  ›  技术社区  ›  expenguin

基于服务变量显示元素(由其他组件设置)

  •  0
  • expenguin  · 技术社区  · 6 年前

    我有一个应用程序,我试图在其中显示或隐藏基于服务中公共变量的元素。此变量的实例化方式如下 show: boolean = false; 然后从子组件进行设置。

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

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

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

    代码如下:

    app.component.html(应用程序组件.html)

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

    App.组件

    export class AppComponent implements OnInit {
    
        constructor(private appService: AppService) {}
    
        ngOnInit() {}
    }
    

    AppService

    export class AppService {
    
        public show: boolean = false;
    
        showLoader() {
            this.show = true;
        }
    
        hideLoader() {
            this.show = false;
        }
    }
    

    儿童成分

    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 回复  |  直到 6 年前
        1
  •  1
  •   DJ House    6 年前

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

    这里有一个到StackBlitz的链接,我在这里实现了这个加载程序服务的一个简单版本: https://stackblitz.com/edit/angular-loading-service-subscribe

    编辑:我添加了 child.component 答案。我在Stackblitz上有,但忘了在这里加。

    关键注意事项:

    loading.service.ts 有一个 行为主体 它管理应用程序是否正在加载数据。它自己回来了 .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

        2
  •  1
  •   Roman Lytvynov    6 年前

    使显示区域可见。

    AppService

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

    在任何你需要聆听的地方订阅。

    推荐文章