【问题标题】:Angular 2 manually triggering ngIfAngular 2 手动触发 ngIf
【发布时间】:2016-10-13 03:23:20
【问题描述】:

目前,我的 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

在 Lucas Té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 更改检测?

【问题讨论】:

    标签: angular angular-ng-if


    【解决方案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;
          }
        });
    

    【讨论】:

      【解决方案2】:

      您可以在 html 中直接执行此操作,而不是手动触发

      ng-if="cameraService.camera1 != null"

      【讨论】:

      • 我很乐意为您的回答 +1,因为我没有意识到我可以直接从 HTML 引用注入的服务(所以感谢您的建议!),但不幸的是,我仍然遇到同样的问题一旦 cameraService 对象发生变化,ngIf 仍然需要手动触发。
      • 组件的更改检测将获取对服务的更改:plnkr.co/edit/lxgAJs
      • 因此,根据您的建议,我进一步研究了它。我将在 Angular 2 区域之外进行初始点击(使用 JavaScript 导入的 Google Map 对象)。当我单击 Google 地图中的静态对象时,JavaScript 会处理单击事件(由于 Google 地图),即使变量已更新,ngIf 更改检测也不会发生。当我在其他任何地方与网站进行交互时(字面意思是通过单击其他任何地方),视图就会更新并且相机会出现。我假设我必须查看 ngZone 的地图点击事件。
      • Lucas Tétreault,我对问题添加了第二个编辑以更好地解释我的场景。我有一个 JavaScript“侦听器”,不幸的是我无法删除它,这是初始化相机的函数链的开始(并将其变量更改为 null 以外的其他值)。
      【解决方案3】:

      我知道我迟到了,但在 Angular 世界中有几种方法可以实现这样的事情。对于这种情况,我个人更喜欢使用BehaviorSubject observable。本质上,在您的相机服务中,您将实例化一个 BehaviorSubject 可观察对象,然后在您的组件中订阅它,并将每次更新时的输出保存到组件内的属性中,这将是您运行 *ngIf 的对象。我在几个项目中都这样做过,效果很好。

      camera.service.ts

      private cameraStatus: BehaviorSubject<ModalProperties> = new BehaviorSubject<boolean>(false);
          cameraStatus$ = this.cameraStatus.asObservable();
      
      updateCameraStatus(status: boolean) {
          this.cameraStatus.next(status);
      }
      

      component-where-you-update-camera-status.ts

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

      your-component.component.ts

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

      【讨论】:

        猜你喜欢
        • 2017-11-29
        • 1970-01-01
        • 2018-07-08
        • 2016-09-17
        • 2016-07-24
        • 1970-01-01
        • 1970-01-01
        • 2018-06-21
        • 1970-01-01
        相关资源
        最近更新 更多