在Angular 6中在组件和服务之间共享变量

时间:2018-07-27 11:18:06

标签: angular

我需要在Angular 6中实现一个加载/旋转器图像。旋转器应在HTTP服务发送请求时显示,并在服务收到响应时隐藏。

我在组件中实现了图像,请注意loading变量:

@Component({
  selector: 'my-spinner',
  templateUrl: `
            <div class="center-all" *ngIf="loading">
                 <img src="spinner.gif"></img>
            </div> 
  `,
  styles: [ `
      .center-all {
          position: fixed; 
          top: 0; 
          left: 0;
          z-index: 99999;
          margin: -8px;
      }
  `],
})
export class MySpinnerComponent {}

我的HTTP服务应直接更改loading变量(而不传递声明MySpinnerComponent并调用MyHttpService的父组件)。

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

    loading = false;

    constructor(private http: HttpClient) {}

    static handleError (error: Response) {
      console.error(error);
      return Observable.throw(error || 'Server error');
    }

    public call (params) {

       this.loading = true;  // how to share this variable with the spinner component?

        return this.http.post<any>(params.url, params.data).
          pipe(
              map(response => response),
              tap(this.loading = false),
              catchError(VbkHttpService.handleError)
          );
    }

}

在AngularJS中,我在$rootScope中声明了变量,以便可以共享它。但是如何在Angular 6中实现等效功能?

2 个答案:

答案 0 :(得分:1)

将事件发射器添加到服务

loadingChange=new EventEmitter<boolean>();

每次更改loading字段时,都使用this.loadingChange.emit(this.loading)发出事件;

并在微调器组件中,订阅该事件发射器。

    @Component({
      selector: 'my-spinner',
      templateUrl: `
                <div class="center-all" *ngIf="loading">
                     <img src="spinner.gif"></img>
                </div> 
      `,
      styles: [ `
          .center-all {
              position: fixed; 
              top: 0; 
              left: 0;
              z-index: 99999;
              margin: -8px;
          }
      `],
    })
    export class MySpinnerComponent{

    loading=false;

    constructor(private service:MyService){
        this.myService.loadingChange.subscribe(flag=>this.loading=flag);
    }
}

OR

您也可以简单地将loading字段设为公开,然后直接从时间表中访问它,如下所示:

服务:

public loading;

组件

  @Component({
      selector: 'my-spinner',
      templateUrl: `
                <div class="center-all" *ngIf="service.loading">
                     <img src="spinner.gif"></img>
                </div> 
      `,
      styles: [ `
          .center-all {
              position: fixed; 
              top: 0; 
              left: 0;
              z-index: 99999;
              margin: -8px;
          }
      `],
    })
    export class MySpinnerComponent{
    constructor(private service:MyService){
    }
}

我只喜欢“发射器”方式

答案 1 :(得分:1)

旋转器应在组件而不是服务中处理。

当您从对方处致电服务时:

  someFunction() {
    this.loading = true; // This will display a child spinner component
    this._service.call().subscribe({
      next: (result) => {
        // Do something with result here
      },
      error: (err) => { // handle error here
        this.loading = false;
      },
      complete: () => {
        this.loading = false;
      }
    });
  }

呼叫完成后-将呼叫“完成”并隐藏微调框。

编辑:添加注释中提到的错误处理。

希望这会有所帮助:)