見出し画像

ちょい技。Lightning Web ComponentsでTooltipを表示する。

Lightning Web Componentsでツールチップを表示しようと思ったら、標準コンポーネントがありません。

ツールチップって使う側にとっては便利なんですよね。

Lightning Web Componentsでツールチップを表示する方法をご紹介します。

こういうものを作成します

行動(Event)の情報をツールチップに表示します。

画像1

ツールチップコンポーネントを作ります

まずは、ツールチップコンポーネントCalendarTooltipを作ります。

CalendarTooltip.html

<template>
   <div class="slds-popover slds-popover_tooltip slds-nubbin_top-left cal-tooltip" role="tooltip" id="tooltip">
       <div class="slds-popover__body">
           <div>
               {dateTime}
           </div>
           <div>
               {subject}
           </div>
           <div>
               {what}
           </div>
           <div>
               {description}
           </div>
       </div>
   </div>
</template>

CalendarTooltip.js

showメソッドでツールチップを表示、hideで非表示にします。

import { LightningElement, api } from 'lwc';

export default class CalendarTooltip extends LightningElement {
   /**
    * 日付時刻
    */
   dateTime;

   /**
    * 件名
    */
   subject;

   /**
    * 関連先名
    */
   what;

   /**
    * 説明
    */
   description;

   /**
    * 表示
    */
   @api show(top, left, event) {
       // ツールチップに表示する行動情報を設定する
       this.dateTime = event.startdate + ((event.isallday) ? '' : (' ' + event.starttime));
       if(event.startdate !== event.enddate) {
           this.dateTime += ' - ' + event.enddate + ((event.isallday) ? '' : (' ' + event.endtime));
       }
       this.subject = event.subject;
       this.what = event.what;
       this.description = event.description;

       // 表示位置を設定する
       const tooltip = this.template.querySelector('.cal-tooltip');
       tooltip.style.top = (top + 20).toString() + 'px';
       tooltip.style.left = left.toString() + 'px';

       // ツールチップを表示する
       tooltip.style.display = 'block';
   }

   /**
    * 非表示
    */
   @api hide() {
       // ツールチップを非表示にする
       const tooltip = this.template.querySelector('.cal-tooltip');
       tooltip.style.display = 'none';
   }
}

CalendarTooltip.css

表示位置を絶対位置にします。

.cal-tooltip {
   position: absolute;
   left: 0px;
   top: 0px;
   display: none;
}

ツールチップを表示する側を作ります

テーブル(Table)のカラム(td)に、onmouseoverとonmouseoutのイベントを設定し、onmouseoverイベントハンドラでツールチップを表示、onmouseoutイベントでツールチップを消します。

Component.html

<template>
   <div class="slds-grid">
       <div class="slds-col">
           <div class="slds-m-left_x-small">
               <span class="cal-header-label">{calendarLabel}</span>
           </div>
       </div>
       <div class="slds-col">
           <div class="slds-float_right">
               <lightning-button-group class="slds-m-right_x-small">
                   <lightning-button-icon icon-name="utility:chevronleft" onclick={handleMovePrevMonth}></lightning-button-icon>
                   <lightning-button variant="neutral" label={labels.CalendarToday} onclick={handleMoveToday}></lightning-button>
                   <lightning-button-icon icon-name="utility:chevronright" onclick={handleMoveNextMonth}></lightning-button-icon>
               </lightning-button-group>
           </div>
       </div>
   </div>
   <div class="slds-grid">
       <div class="slds-col">
           <table class="cal-table">
               <tbody>
                   <tr>
                       <template for:each={weeks} for:item="week">
                           <td class={week.class} key={week.label}>
                               <span>{week.label}</span>
                           </td>
                       </template>
                   </tr>
               </tbody>
           </table>
           <template for:each={items} for:item="week">
               <table key={week.date} class="cal-table">
                   <thead>
                       <tr>
                           <template for:each={week.days} for:item="day">
                               <th key={day.date} class={day.class}>
                                   <span>{day.day}</span>
                               </th>
                           </template>
                       </tr>
                   </thead>
                   <tbody>
                       <template for:each={week.rows} for:item="row">
                           <tr key={row.id}>
                               <template for:each={row.events} for:item="event">
                                   <template if:true={event.isdummy}>
                                       <td key={event.id} class="cal-day-event-none">
                                       </td>
                                   </template>
                                   <template if:false={event.isdummy}>
<!-- ここです -->
                                       <td key={event.id} class="cal-day-event" colspan={event.span} data-id={event.id} onmouseover={handleMouseOverToEvent} onmouseout={handleMouseOutFromEvent}>
                                           {event.labelshort}
                                       </td>
                                   </template>
                               </template>
                           </tr>
                       </template>
                   </tbody>
               </table>
           </template>
       </div>
   </div>
   <c-calendar-tooltip>
   </c-calendar-tooltip>
</template>

Component.js

onmouseoverイベントハンドラ(handleMouseOverToEvent)でツールチップの表示位置を指定しています。

layerXとlayerYを使うとツールチップらしい位置に表示できます。

import { LightningElement, api, track } from 'lwc';

export default class CalendarMonthly extends LightningElement {
   /**
    * 行動情報
    */
   _events;

   /**
    * 行動アイテムにマウスが入ったらツールチップを表示する
    */
   handleMouseOverToEvent(evt) {
       evt.stopPropagation();

       // 行動IDから行動情報を取得する
       const event = this.getEvent(evt.target.dataset.id);

       // 行動の詳細をツールチップで表示する
       this.template.querySelector('c-calendar-tooltip').show(evt.layerY, evt.layerX, event);
   }

   /**
    * 行動アイテムからマウスが離れたらツールチップを非表示にする
    */
   handleMouseOutFromEvent(evt) {
       evt.stopPropagation();

       // 行動のツールチップを非表示する
       this.template.querySelector('c-calendar-tooltip').hide();
   }

   /**
    * ID指定で行動情報を取得する
    */
   getEvent(id) {
       let event = null;
       for(let i=0 ; i<this._events.length ; i++) {
           if(this._events[i].id === id) {
               event = this._events[i];
               break;
           }
       }
       return event;
   }
}

やっぱり、ツールチップはどうしても必要です。


この記事が気に入ったらサポートをしてみませんか?