Angular changeDetector.detectChanges打破* ngFor中的matTooltip

如何解决Angular changeDetector.detectChanges打破* ngFor中的matTooltip

以下组件中的matTooltip正确变红。呈现了工具提示的叠加层和小气泡,但是缺少了文本(尽管在浏览器中进行检查时是在html中),并且位置不正确。

有趣的是,该工具提示在我删除detectChanges()调用时有效,或者即使在detectChanges();下也可以在* ngFor之外使用

@Component({
  selector: 'mur-app-titlebar',templateUrl: './app-titlebar.component.html',styleUrls: ['./app-titlebar.component.scss']
})
export class AppTitlebarComponent implements OnInit,OnDestroy {
  public appbarItems: IMenuItem[];

  private destroy$ = new Subject();

  constructor(
    private appBarService: AppBarService,// my custom service
    private changeDetector: ChangeDetectorRef,) {
  }

  public ngOnInit() {
    this.appBarService.getAppbarItems().pipe( //observable comes from outside of angular
      takeuntil(this.destroy$)
    ).subscribe(value => {
      this.appbarItems = value || [];
      // change detection is not triggered automatically when the value is emmited
      this.changeDetector.detectChanges(); 
    });
  }

  public ngOnDestroy() {
    this.destroy$.next();
  }

}
<ng-container *ngFor="let item of appbarItems">
      <button mat-button
              (click)="item.onclick && item.onclick()"
              [disabled]="item.disabled"
              [matTooltip]="item.tooltip"
              [style.color]="item.color">
        <mat-icon *ngIf="item.icon"
                  [class.mr-3]="item.label">
          {{item.icon}}
        </mat-icon>
        <span>{{item.label}}</span>
      </button>
     
    </ng-container>

我已经确认,appbarItems仅设置了一次并且没有改变

解决方法

通常,您无需在Angular中的异步操作的回调中调用cdRef.detectChanges()

但是,如果这样做,则意味着您正在尝试解决视图更新中的某些问题。异步代码后未更新组件视图的原因可能有多种:

  • 您的组件被隐藏以根据OnPush更改检测策略进行检查

  • 回调是在Angular区域之外执行的。

好像您遇到了第二种情况。在Angular区域之外调用cdRef.detectChanges会给您带来一些情况,即某些Angular处理程序将在Angular区域之外注册。结果,这些处理程序将不会更新视图,并且您将在其他位置调用detectChanges或再次使用zone.run。

以下是这种情况的一个示例https://ng-run.com/edit/XxjFjMXykUqRUC0irjXD?open=app%2Fapp.component.ts

您的解决方案可能是通过使用ngZone.run方法将代码执行返回到Angular区域:

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

constructor(private ngZone: NgZone) {}

.subscribe(value => {
  this.ngZone.run(() => this.appbarItems = value || []);
  

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?