在页面滚动时打开上方的角度材料工具提示并避免工具提示被隐藏 [英] To open angular material tooltip above when the page is scrolled and avoid the tooltip getting hidden
问题描述
我在 stackblitz 链接中添加了 2 个表格,如果我将鼠标悬停在第一个表格(第一列)中,工具提示会在上方打开(预期)但是当我们向下滚动时页面,然后将鼠标悬停在第二个表格的最后几行上,工具提示会隐藏在屏幕底部,如果我只有一个表格,则情况并非如此.我期待工具提示在上方打开而不是隐藏在底部.请提出建议.
Stacblitz 链接
https://stackblitz.com/edit/angular-mat-tooltip-ctvigc?file=app%2Ftooltip-overview-example.html
tooltip-overview-example.html
<th mat-header-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屋!