在页面滚动时打开上方的角度材料工具提示并避免工具提示被隐藏 [英] To open angular material tooltip above when the page is scrolled and avoid the tooltip getting hidden

查看:23
本文介绍了在页面滚动时打开上方的角度材料工具提示并避免工具提示被隐藏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Stacblitz 链接

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

tooltip-overview-example.html

<th mat-h​​eader-cell *matHeaderCellDef mat-sort-header>警报</th><td mat-cell *matCellDef="let row;让 i = 索引"customToolTip [contentTemplate]=模板"><span >{{row.Column1}}</span><!--工具提示--><ng-template #template><div style="display: flex;flex-direction: column"><span>{{row.conditionals |json}}</span><按钮(点击)=onClick(i)">点击</button>

</ng-模板></td></ng-容器>

在 CustomToolTipComponent 中扩展了 Angular 材质 TooltipComponent

custom-tool-tip.component.ts

import {成分,初始化,在销毁,输入,模板引用来自@angular/core";从@angular/material/tooltip"导入 {TooltipComponent};import { Observable, Subject } from "rxjs";@成分({选择器:app-custom-tool-tip",templateUrl: "./custom-tool-tip.component.html",styleUrls: [./custom-tool-tip.component.css"]})导出类 CustomToolTipComponent 扩展 TooltipComponent {@Input() 文本:字符串;@Input() contentTemplate: TemplateRef;}

custom-tool-tip.component.html

<div class="tooltip-conatiner"><ng-template #simpleText>{{文本}}</ng-模板><ng-container *ngTemplateOutlet="contentTemplate ||简单文本"></ng-容器>

tool-tip-renderer.directive.ts

@Directive({选择器:[customToolTip]"})导出类 ToolTipRendererDirective {@Input() showToolTip: boolean = true;//如果指定,则指定的文本将显示在工具提示中@Input(`customToolTip`) 文本:字符串;//如果指定,则指定的模板将在工具提示中呈现@Input() contentTemplate: TemplateRef;私有_overlayRef: OverlayRef;私人 _tooltipInstance;私人 _mouseInTooltip:布尔值 = 假;私人_hasListeners:布尔=假;构造函数(私人_overlay:覆盖,私人 _overlayPositionBuilder: OverlayPositionBuilder,私有 _elementRef: ElementRef,私有_r2:渲染器2) {}ngOnInit() {如果(!this.showToolTip){返回;}const positionStrategy = this._overlayPositionBuilder.flexibleConnectedTo(this._elementRef).withPositions([{originX:中心",originY:底部",叠加X:中心",叠加Y:顶部",偏移量:-10}]);this._overlayRef = this._overlay.create({ positionStrategy });}@HostListener(鼠标输入")显示(e){如果 (this._overlayRef && !this._overlayRef.hasAttached()) {//设置工具提示实例this._tooltipInstance = this._overlayRef.attach(新的组件门户(CustomToolTipComponent)).实例;//设置 CustomToolTipComponenet 内容/输入this._tooltipInstance.text = this.text;this._tooltipInstance.contentTemplate = this.contentTemplate;//渲染工具提示this._tooltipInstance!.show(0);//隐藏动画完成后分离this._tooltipInstance.afterHidden().pipe(take(1)).subscribe(() => {this._overlayRef.detach();});如果(!this._hasListeners){this._hasListeners = true;//当鼠标离开工具提示时附加鼠标离开侦听器以分离this._r2.listen(this._overlayRef.overlayElement, mouseleave", () => {//在该指令中调用隐藏函数this._mouseInTooltip = false;this.hide();});this._r2.listen(this._overlayRef.overlayElement, "mouseenter", () => {//在该指令中调用隐藏函数this._mouseInTooltip = true;});}}}@HostListener(鼠标离开")隐藏(buttonClicked = null){如果(按钮点击)this._mouseInTooltip = false;setTimeout(() => {if (!this._mouseInTooltip) this._tooltipInstance!._onHide.next();}, 20);}}

解决方案

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

根据此方法,您可以在附加后更改叠加层的位置策略.

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

this._overlayRef.updatePositionStrategy(this._overlayPositionBuilder.flexibleConnectedTo(this._elementRef).withPositions([{originX: "中心",originY: "底部",叠加X:中心",叠加Y:顶部",offsetY: this.getOffsetY()}]));this._overlayRef.updatePosition();

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

private getOffsetY() {如果 (this._elementRef.nativeElement.getBoundingClientRect().bottom > 500)返回-400;如果 (this._elementRef.nativeElement.getBoundingClientRect().bottom > 400)返回-300;如果 (this._elementRef.nativeElement.getBoundingClientRect().bottom > 300)返回-200;返回-10;}

这里是 stackblitz 链接

I have added 2 tables in stackblitz link, if I hover in first table(1st column) alst rows the tooltip opens above(expected) but when we scroll down the page and then hover on the last rows of 2nd table, the tooltip gets hidden in the bottom of the screen, as was not the case if I have a single table. I was expecting the tooltip to be opened above instead of getting hidden in the bottom. Please suggest.

Stacblitz link

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>

Extended the Angular material TooltipComponent in CustomToolTipComponent

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);
}
}

解决方案

To fix this, you need to upgrade your cdk version to 7.3.7 which has a new method on OverlayRef as updatePositionStrategy.

According to this method you can change the position strategy of an overlay after attach.

In your show function after attaching the component you need to update position strategy as below:

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

where this.getOffsetY() is private method provide offset y value based on element current position. You may need to update this logic.

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;
}

Here is stackblitz link

这篇关于在页面滚动时打开上方的角度材料工具提示并避免工具提示被隐藏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆