Чтобы открыть всплывающую подсказку angular для материала выше при прокрутке страницы и избежать ее скрытия - PullRequest
1 голос
/ 13 апреля 2020

Я добавил 2 таблицы в ссылке на стекаблиц, если я наведу курсор на первую таблицу (1-й столбец) над строками, всплывающая подсказка открывается выше ( ожидается ), но когда мы прокручиваем страницу вниз и затем наведите курсор на последние строки 2-й таблицы, всплывающая подсказка будет скрыта в нижней части экрана, как это было в случае с одной таблицей. Я ожидал, что всплывающая подсказка будет открыта вверху, а не спрятана внизу. Пожалуйста, предложите.

Ссылка на Stacblitz

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

обзор подсказок -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>

Расширена всплывающая подсказка Angular материала в 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);
}
}

Ответы [ 2 ]

2 голосов
/ 15 апреля 2020

Чтобы исправить это, вам нужно обновить версию cdk до 7.3.7, в которой для OverlayRef используется новый метод updatePositionStrategy.

В соответствии с этим методом вы можете изменить стратегию позиционирования наложения после присоединения.

В вашей функции показа после присоединения компонента вам необходимо обновить стратегию положения, как показано ниже:

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 на основе текущей позиции элемента. Вам может потребоваться обновить эту логику c.

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

Вот блик стека ссылка

0 голосов
/ 13 апреля 2020

Вы можете получить положения event.screenX и Event event.screenY и с помощью этого проверить высоту экрана, получив высоту экрана и ширину экрана.

screen.height

Затем проверьте если событие не близко к высоте экрана, тогда сделайте [matTooltipPosition]="position.value" выше ..

Вот так вы должны проверить

...