在页面滚动时打开上方的角度材料工具提示并避免工具提示被隐藏

Posted

技术标签:

【中文标题】在页面滚动时打开上方的角度材料工具提示并避免工具提示被隐藏【英文标题】:To open angular material tooltip above when the page is scrolled and avoid the tooltip getting hidden 【发布时间】:2020-07-26 06:04:35 【问题描述】:

我在 stackblitz 链接中添加了 2 个表格,如果我将鼠标悬停在第一个表格(第一列)alst 行中,工具提示会在上方打开(预期)但是当我们向下滚动时页面,然后将鼠标悬停在第二个表的最后一行,工具提示隐藏在屏幕底部,如果我有一个表,情况就不是这样。 我期待工具提示在上方打开而不是隐藏在底部。请提出建议。

Stacblitz 链接

https://stackblitz.com/edit/angular-mat-tooltip-ctvigc?file=app%2Ftooltip-overview-example.html

tooltip-overview-example.html

<ng-container matColumnDef="Column1">
     <th mat-header-cell *matHeaderCellDef mat-sort-header> Alert </th>

     <td mat-cell *matCellDef="let row; let i = index" customToolTip [contentTemplate]="template">
          <span >row.Column1</span>
     <!--TOOLTIP-->
      <ng-template #template>
          <div style="display: flex; flex-direction: column">
             <span>row.conditionals | json</span>
             <button (click)="onClick(i)">Click</button>
          </div>
      </ng-template>
      </td>

</ng-container>

在 CustomToolTipComponent 中扩展了 Angular 材质 TooltipComponent

custom-tool-tip.component.ts

import 
 Component,
 OnInit,
 OnDestroy,
 Input,
 TemplateRef
  from "@angular/core";
 import TooltipComponent from "@angular/material/tooltip"
 import  Observable, Subject  from "rxjs";

@Component(
 selector: "app-custom-tool-tip",
 templateUrl: "./custom-tool-tip.component.html",
 styleUrls: ["./custom-tool-tip.component.css"]
)
export class CustomToolTipComponent extends TooltipComponent 

 @Input() text: string;
 @Input() contentTemplate: TemplateRef<any>;


custom-tool-tip.component.html

<div>
 <div class="tooltip-conatiner">
  <ng-template #simpleText>
  text
  </ng-template>
  <ng-container *ngTemplateOutlet="contentTemplate || simpleText">
  </ng-container>
</div>
</div>

tool-tip-renderer.directive.ts

@Directive(
  selector: "[customToolTip]"
)
export class ToolTipRendererDirective 

@Input() showToolTip: boolean = true;

//If this is specified then specified text will be showin in the tooltip
 @Input(`customToolTip`) text: string;

//If this is specified then specified template will be rendered in the tooltip
 @Input() contentTemplate: TemplateRef<any>;

private _overlayRef: OverlayRef;
private _tooltipInstance;
private _mouseInTooltip: boolean = false;
private _hasListeners: boolean = false;

constructor(
 private _overlay: Overlay,
 private _overlayPositionBuilder: OverlayPositionBuilder,
 private _elementRef: ElementRef,
 private _r2: Renderer2
 ) 


ngOnInit() 
 if (!this.showToolTip) 
  return;


const positionStrategy = this._overlayPositionBuilder
  .flexibleConnectedTo(this._elementRef)
  .withPositions([
    
      originX: "center",
      originY: "bottom",
      overlayX: "center",
      overlayY: "top",
      offsetY: -10
    
  ]);

this._overlayRef = this._overlay.create( positionStrategy );



@HostListener("mouseenter")
show(e) 
if (this._overlayRef && !this._overlayRef.hasAttached()) 
  //set tooltip instance
  this._tooltipInstance = this._overlayRef.attach(
    new ComponentPortal(CustomToolTipComponent)
  ).instance;

  //set CustomToolTipComponenet content/inputs
  this._tooltipInstance.text = this.text;
  this._tooltipInstance.contentTemplate = this.contentTemplate;

  //render tooltip
  this._tooltipInstance!.show(0);

  //sub to detach after hide anitmation is complete
  this._tooltipInstance
    .afterHidden()
    .pipe(take(1))
    .subscribe(() => 
      this._overlayRef.detach();
    );
  if (!this._hasListeners) 
    this._hasListeners = true;
    //attach mouseleave listener to detach when mouseleave on tooltip
    this._r2.listen(this._overlayRef.overlayElement, "mouseleave", () => 
      //call hide function in this directive
      this._mouseInTooltip = false;
      this.hide();
    );

    this._r2.listen(this._overlayRef.overlayElement, "mouseenter", () => 
      //call hide function in this directive
      this._mouseInTooltip = true;
    );
  



@HostListener("mouseleave")
hide(buttonClicked = null) 
if(buttonClicked)
  this._mouseInTooltip = false;
setTimeout(() => 
  if (!this._mouseInTooltip) this._tooltipInstance!._onHide.next();
, 20);


【问题讨论】:

stackblitz 链接在哪里? @GouravGarg,我错过了,现在已经添加,谢谢 你能把你的项目更新到 Angular 7 吗? 【参考方案1】:

要解决此问题,您需要将 cdk 版本升级到 7.3.7,它在 OverlayRef 上有一个新方法,即 updatePositionStrategy。

根据这个方法,你可以在attach之后改变overlay的位置策略。

在附加组件后的显示功能中,您需要更新位置策略,如下所示:

this._overlayRef.updatePositionStrategy(this._overlayPositionBuilder
  .flexibleConnectedTo(this._elementRef)
  .withPositions([
    originX: "center",
    originY: "bottom",
    overlayX: "center",
    overlayY: "top",
    offsetY: this.getOffsetY()
  ]));
this._overlayRef.updatePosition();

this.getOffsetY() 是私有方法,根据元素当前位置提供偏移 y 值。您可能需要更新此逻辑。

private getOffsetY() 
  if (this._elementRef.nativeElement.getBoundingClientRect().bottom > 500)
    return -400;
  if (this._elementRef.nativeElement.getBoundingClientRect().bottom > 400)
    return -300;
  if (this._elementRef.nativeElement.getBoundingClientRect().bottom > 300)
    return -200;
  return -10;

这里是 stackblitz link

【讨论】:

谢谢,这很好用,但是当我悬停在最后 2 行的底部时,工具提示会在第一行上方打开,而不是在鼠标悬停的行上,因为它在顶部行中打开就在悬停行的下方或上方,所以我将 getOffsetY() 函数的返回值更改为较小的数字,而不是 -400 ,更改为 -100 , -80 ,这是正确的方法吗 是的,我提到过,您需要根据实际外观和感觉进行更改 一件事,但如果表格中有更多行数并且我向下滚动,则不考虑滚动值,并且再次开始隐藏在底部,stackblitz.com/edit/angular-mat-tooltip-h2jxgc?file=app/… 您需要围绕此创建一个公式。就像 500 一样,您可以执行 (500/-10)-50 之类的操作,这将返回 -100 或与元素和主体之间的空间相关的内容 是的,但我认为我应该考虑页面滚动的程度,以防万一滚动 oage 我应该补充一点,我应该如何在这个指令中注册它并在 y 中修改,因为我的主要问题是,当页面滚动并且底部行悬停时隐藏工具提示【参考方案2】:

您可以获取 event.screenX 和 Event event.screenY 位置,并使用它通过获取屏幕高度和屏幕宽度来检查屏幕的高度。

screen.height

然后检查事件是否靠近屏幕高度,如果然后使[matTooltipPosition]="position.value"高于..

像这样你必须检查

【讨论】:

[matTooltipPosition]=position。在此处传递值 能否请您详细说明我应该通过哪个文件的位置,无法理解 ***.com/questions/60883450/… 已解决?

以上是关于在页面滚动时打开上方的角度材料工具提示并避免工具提示被隐藏的主要内容,如果未能解决你的问题,请参考以下文章

材料角度:自动滚动到无效输入并打开matstepper。

如何在开始滚动和透明后将角度材质工具栏背景颜色更改为白色?

Twitter Bootstrap Twipsy - 悬停在工具提示上方

chrome开发者工具使用的总结

UIScrollView里面的UIWebView上面的UIToolbar

visualstudio添加一行标题