Angular 2手动触发ngIf

时间:2016-10-13 03:23:20

标签: angular angular-ng-if

目前,我的DOM对象如下所示:

<div *ngIf="checkCam1Exists()">
  <app-counter [index]="1"></app-counter>
</div>

在组件中,函数'checkCam1Exists()'如下所示:

checkCam1Exists(){
  console.log("checkCam1ran");
  if(this.cameraService.camera1 == null){
    return false;
  }
  else{
    return true;
  }
}

其中cameraService是注入组件构造函数的服务,而camera1是cameraService中的对象。

我的问题在于让ngIf再次运行。 camera1对象从另一个服务(发出HTTP请求的dataService)中更新。如何触发ngIf再次运行?

我已阅读以下帖子: Triggering Angular2 change detection manually - 但Angular文档中提供的示例似乎没有涵盖如何检查组件类之外的变量(我需要检查服务变量)。

修改

我设法使用以下方法进行自动更改检测:

constructor(private ref: ChangeDetectorRef, private cameraService: CameraService, private toolbarService: ToolbarService) {
    ref.detach();
    setInterval(() => {
      this.ref.detectChanges();
    }, 5000);
  }

虽然这感觉就像一种非常低效的方式。如何手动触发更改检测?

编辑2

在LucasTétreault的帮助下,我想我可能会在Angular 2区域之外进行初始点击事件,因为与应用程序的任何交互(在初始点击事件之后)都会导致ngIf检测到更改并再次开始工作。 我的问题必须在这里:

map.data.addListener('click', (event) => {
      var mapElement = event.feature.getProperty('type');
      switch(mapElement){
        case 'classifiedroads':
          var roadnumber = event.feature.getProperty('roadID');
          map.data.revertStyle();
          map.data.overrideStyle(event.feature, {
            strokeWeight: 8
          });
          this.roadService.roadClicked(roadID);
          break;
        case 'cameras':
          var cameraID = event.feature.getProperty('trafficID');
          this.cameraService.cameraClicked(cameraID); //camera is initialised at this stage.
          break;
        default:
          break;
      }
    });

我有一个使用JavaScript导入的Google Map对象(Angular2 Google Map项目存在一些限制,我被警告过,这就是我不使用它的原因)。此单击事件必须超出Angular 2区域,当我单击应用程序上的其他位置时,我会重新进入Angular 2区域并再次启动ngIf更改检测。

有没有办法可以手动强制进行ngIf更改检测?

3 个答案:

答案 0 :(得分:1)

这最终对我有用。

我认为这与我所做的研究是正确的: 将Google Maps与AddListener一起使用意味着在Angular 2区域之外创建JavaScript侦听器。这意味着如果变量或某些内容发生变化,则不会触发Angular 2的变化检测。要解决这个问题,请在类的构造函数中注入NgZone:

constructor(private cameraService: CameraService, private ngZone: NgZone)...

使用NgZone的'.run()'重新进入Angular 2区域:

map.data.addListener('click', (event) => {
      var mapElement = event.feature.getProperty('type');
      switch(mapElement){
        case 'cameras':
          var cameraID = event.feature.getProperty('traffic_asset_bk');
          this.ngZone.run(
              () => this.cameraService.cameraClicked(station_key)
          );
          break;
        default:
          break;
      }
    });

答案 1 :(得分:0)

而不是手动trigerring你可以在html

中做到这一点

ng-if =&#34; cameraService.camera1!= null&#34;

答案 2 :(得分:0)

我知道我迟到了,但是在Angular世界中有几种方法可以实现这样的事情。就个人而言,我更喜欢使用BehaviorSubject观察。基本上在您的相机服务中,您将实例化一个BehaviorSubject可观察对象,然后在您的组件中订阅它,并在每次更新时将输出保存到组件中的属性,这将是您运行* ngIf的对象。我已经在几个项目中完成了这项工作并且运行良好。

<强> camera.service.ts

private cameraStatus: BehaviorSubject<ModalProperties> = new BehaviorSubject<boolean>(false);
    cameraStatus$ = this.cameraStatus.asObservable();

updateCameraStatus(status: boolean) {
    this.cameraStatus.next(status);
}

<强>组件,其中,你更新相机-status.ts

turnCameraOn() {
    this._CameraService.updateCameraStatus(true);
}

您-component.component.ts

componentVisibile: boolean

this_CameraService.cameraStatus$.subscribe(
    _CameraStatus => {
        this.componentVisible = _CameraStatus;
    }
)