从服务到组件的角度数据绑定

时间:2018-08-10 13:05:07

标签: javascript angular typescript promise observable

我想在发送Http请求时显示加载指示器。 我尝试使用Angular Http Interceptor,但指标样式永远不会更新。

我的app.component.html中有一个loading indicator

StoreManager::StoreManager() {
   // Verify that the version of the library that we linked against is
   //   // compatible with the version of the headers we compiled against.
   GOOGLE_PROTOBUF_VERIFY_VERSION;

  // file = "data.db";
  // // Read the existing data.
  input = fstream(file, ios::in | ios::binary);
  if (!input) { 
      input.close();
      cout << file << ": File not found. Creating a new file." << endl;
      fstream output(file, ios::out | ios::trunc | ios::binary);
      if (!output)
          cout << file << ": Failed to create a new file" << endl;
      else{
          appData.SerializeToOstream(&output);
          output.close();
          cout << file << ": New empty file created " << endl;
      }

      input = fstream(file, ios::in | ios::binary);
      if (!input) { 
          cout << file << ": File not found. Failed to creating a new file." << endl;
      }
  } 

  if (!appData.ParseFromIstream(&input)) {
      cerr << "Failed to parse in date storage." << endl;
  } 
}

AppData* StoreManager::getData() {
  return &appData;
}

void StoreManager::save(){
  // Write back to disk.
  fstream output(file, ios::out | ios::trunc | ios::binary);
  if (!appData.SerializeToOstream(&output)) {
     cerr << "Failed to write in date storage." << endl;
  }
  output.close();
}

这是app.component.ts:

  <div [style.display]="visibilityOfLoadingIndicator">
    <mat-progress-bar mode="indeterminate" color="warn" ></mat-progress-bar>
  </div>

这是HttpLoadingIndicatorService.ts:

export class AppComponent {


  visibilityOfLoadingIndicator = 'none';

  constructor(public loadingIndicatorService: LoadingIndicatorService) {
    this.loadingIndicatorService.getLoadingIndicator()
    .subscribe(visibility => {
      this.visibilityOfLoadingIndicator = <string> visibility;
    });

    }
  }

我的服务正在运行,例如,这是控制台输出:

@Injectable({
  providedIn: 'root'
})
export class LoadingIndicatorService implements HttpInterceptor {


  private display;

  private loadingIndicator: EventEmitter<string>;

  constructor() {
  this.loadingIndicator = new  EventEmitter<string>();
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const started = Date.now();
    console.log('Request started');
    this.display = 'block';
    this.updateVisibility(this.display);
    return next.handle(req)
      .pipe(
        finalize(
          () => {
            const elapsed = Date.now() - started;
            const msg = `${req.method} "${req.urlWithParams}"
            in ${elapsed} ms.`;
            console.log(msg);
            this.display = 'none';
            this.updateVisibility(this.display);
          }
        )
      )
      ;
  }



  updateVisibility(state: string) {
    this.loadingIndicator.emit(state);
  }

  getLoadingIndicator() {
    return this.loadingIndicator;
  }


}

但是为什么指标样式没有更新?

我应该创建Observable吗?

1 个答案:

答案 0 :(得分:0)

是的,您需要让组件订阅服务中的更改,以便它可以告诉Angular一切已更改。

  constructor(public  authenticationService: AuthenticationService,
              public loadingIndicatorService: HttpLoadingIndicatorService,
              changeDetector: ChangeDetectorRef) {
      loadingIndicatorService.displayChangeObservable.subscribe(() =>
      { 
          changeDetector.markForCheck();
      });
  }

  displayLoadingIndicator() {
    return this.loadingIndicatorService.display;
  }

}

服务

@Injectable({
  providedIn: 'root'
})
export class HttpLoadingIndicatorService implements HttpInterceptor {

  private displayChangeSubject = new Subject<any>();
  public displayChangeObservable = this.displayChangeSubject.asObservable();

  display = 'none';

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const started = Date.now();
    console.log('Request started');
    this.display = 'block';
    this.displayChangeSubject.next();
    return next.handle(req)
      .pipe(
        finalize(
          () => {
            const elapsed = Date.now() - started;
            const msg = `${req.method} "${req.urlWithParams}"
            in ${elapsed} ms.`;
            console.log(msg);
            this.display = 'none';
            this.displayChangeSubject.next();
          }
        )
      )
      ;
  }

}