0

I have a simple drag element example from angular documentation, in which I have a button that can be dragged around in the container, and the button has a tooltip.

<div class="example-boundary">
      <div class="example-box"
           cdkDragBoundary=".example-boundary" 
           (cdkDragEnded)="onCircleButtonDragEnd($event)">
      </div>
      <div class="tool-tip">
        I am tooltip
      </div>
 </div>
.example-boundary {
  position: relative;
  border: 1px dotted gray;
  position: relative;
  border: 1px dotted gray;
  width: 40vh;
  height: 40vh;
  margin: 0 10vmin;
  margin: 0 10vmin;
}

.example-box {
  position: absolute;
  width: 16px;
  height: 16px;
  background-color: red;
  padding: 10px;
  border-radius: 35px;
  border: 1px solid green;
  cursor: grab;
  left: 50%;
  top: 50%;
}

.example-box:hover + .tool-tip {
  display: block;
}

.tool-tip {
  display: none;
  width: 30%;
  height: 50px;
  border: 2px solid red;
}
@Component({
  selector: "app-page-editor",
  templateUrl: "./page-editor.component.html",
  styleUrls: ["./page-editor.component.scss"],
})

export class PageEditorComponent {
  circleButtonLeft: any;
  circleButtonTop: any;
  showTooltipOnLeft: any;

  constructor(
    private renderer: Renderer2,
    private el: ElementRef,
    private sanitizer: DomSanitizer,
    private data: DataService
  ) {}

  updateTooltipPosition() {
    const tooltipBox = this.el.nativeElement.querySelector(".tool-tip");
    const circleButton = this.el.nativeElement.querySelector(
      ".example-box"
    );
    if (tooltipBox && circleButton) {
      if (this.showTooltipOnLeft) {
        this.renderer.setStyle(
          tooltipBox,
          "left",
          `${circleButton.offsetLeft - tooltipBox.offsetWidth}px`
        );
      } else {
        this.renderer.setStyle(
          tooltipBox,
          "left",
          `${circleButton.offsetLeft + circleButton.offsetWidth}px`
        );
      }
      this.renderer.setStyle(
        tooltipBox,
        "top",
        `${circleButton.offsetTop - tooltipBox.offsetHeight / 2}px`
      );
    }
  }

  onCircleButtonDragEnd(event: any) {
    console.log("event", event);
    const offsetX = event.source.getFreeDragPosition().x;
    const offsetY = event.source.getFreeDragPosition().y;

    this.circleButtonLeft = offsetX;
    this.circleButtonTop = offsetY;

    this.updateTooltipPosition();
  }
}

The expected behavior.

-When the button is dragged to any position inside a container, on hover it should show the tooltip either left side or right side based on the available space

enter image description here

Chris Barr
  • 29,851
  • 23
  • 95
  • 135
The Dead Man
  • 6,258
  • 28
  • 111
  • 193

1 Answers1

0

It's not properly optimized as I couldn't spend much time on it, try it and let me know if works for you: https://stackblitz.com/edit/stackblitz-starters-lterrf?file=src%2Fdirectives%2Ftooltip.directive.ts

the code is pretty explanatory, the idea is to find out when the target element goes out of bounds and running the logic at right time which in your case wasn't happening, cdkDragEnded as the name suggests is going to be fired after you are done dragging the element this is probably not what you want so it's better to run the render logic on mouse enter and destroy the element on mouse leave and to make sure the tooltip follows the target element update it's position on mouse move.

One thing to note here is that cdkDrag applies CSS transform property to move the target element around so if you'll try to read offsetTop or offsetLeft on that element, it's not going to give you the right value so you'll need to rely on getBoundingClientRect.

Yogi
  • 345
  • 1
  • 7