【问题标题】:Angular does not detect changes made from window global functionAngular 不会检测到窗口全局函数所做的更改
【发布时间】:2021-01-21 15:22:30
【问题描述】:

在工作中我遇到了一个很奇怪的行为。

这里是类似问题的linkstackblitz

index.html 文件我提出了一些点击事件

function createClause(event) {
    Office.context.document.getSelectedDataAsync(
      Office.CoercionType.Text,
      (asyncResult) => {
        window.sendSelectedTextCallback({selectedText: asyncResult.value});
        event.completed();
      });
  }

app.component.ts 中,我正在监听sendSelectedTextCallback 函数。

(window as any).sendSelectedTextCallback = (params: any) => {
    clauseCommunicationService.addClause({name: params.selectedText});
};

clauseCommunicationService.addClause 方法调用 next 函数以获得 subject

在某些组件中,我正在监听更改。

this.clauseAddedSubscription = clauseCommunicationService.clauseAdded$.subscribe(
  (clause) => {
    this.clauses.push(clause);
    console.log(this.clauses);
  }
);

我面临的问题是console.log(this.clauses) 命令向我显示更新的列表,但这并未反映在UI 上。

如果我要替换

(window as any).sendSelectedTextCallback = (params: any) => {
    clauseCommunicationService.addClause({name: params.selectedText});
}

setTimeout(() => {
   clauseCommunicationService.addClause({name: 'helloooo'});
 }, 4000);

我可以看到更改反映在 UI 上。

我尝试使用ngZoneChangeDetector 功能但没有成功。

【问题讨论】:

  • this.clauses 是如何声明的?
  • @GetOffMyLawn, public clauses: any[] = [];
  • @GetOffMyLawn,在 onInit 方法中,它使用来自 server 的内容进行初始化
  • 模板是什么样的?如果您使用的是第 3 方工具,您可能需要告诉它数据已更改并需要刷新。
  • @GetOffMyLawn,我正在使用一些第 3 方工具。我已经更新了createClause 方法。

标签: javascript angular events


【解决方案1】:

问题是因为按钮在 Angular 之外,所以 Angular 不会测试按钮上的更改检测,所以当按钮被点击时它不知道发生了什么事情。我们可以使用 @HostListener Stack Blitz example 为该按钮添加更改检测。

export class HelloComponent {
  public elements = [1, 2, 3, 4];

  @HostListener('window:click')
  private onWindowClick() {
    this.cdr.detectChanges();
  }

  constructor(
    @Inject(CommunicationService)
    private communicationService: CommunicationService,
    private cdr: ChangeDetectorRef
  ) {}

  ngOnInit() {
    this.communicationService.elemAdded$.subscribe(elem => {
      this.elements.push(elem);
      console.log(this.elements);
    });
  }
}

【讨论】:

  • 不幸的是,这不适用于我的代码,但适用于 Stackblitz
  • 原因是点击事件发生在office上下文而不是angular app上。
【解决方案2】:

您可以通过使用 ngZone 强制 Angular “刷新”并考虑超出其世界范围的事件和事物:试试这个

import { NgZone } from '@angular/core';

// In the constructor, inject NgZone
constructor(private zone: NgZone) { }

// Then :
clauseCommunicationService.clauseAdded$.subscribe(
     (clause) => {
          this.zone.run(() => { // Where the magic happens
               this.clauses.push(clause);
               console.log(this.clauses);
          })
     }
 );

【讨论】:

  • 不幸的是,这不适用于我的代码,但适用于 Stackblitz
猜你喜欢
  • 1970-01-01
  • 2016-03-26
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 1970-01-01
  • 2021-04-23
  • 1970-01-01
相关资源
最近更新 更多