今回は lightning:overlayLibrary
でポップアップを表示してみました。
単純にポップオーバーを表示するだけであれば特に迷わないのですが、ポップオーバー自体へのマウスホバーで少し迷いました。(これくらい機能として持っていてくれてもいいじゃないか!)
動作イメージ
サンプルコード
SimplePopoverExample.cmp
<aura:component implements="flexipage:availableForAllPageTypes" access="global" >
<!-- Public Attributes -->
<aura:attribute access="public" type="Aura.component" name="popover" />
<aura:attribute access="public" type="Integer" name="closeTimer" />
<!-- Overlay Library -->
<lightning:overlayLibrary aura:id="overlayLib"/>
<!-- User Interface -->
<div>
<lightning:card iconName="utility:quick_text" title="Simple Popover Example">
<lightning:layout>
<lightning:layoutItem padding="around-medium" size="12">
<span class="popoverReference">
<a href="javascript:void(0);" onmouseenter="{!c.onMouseEntered}" onmouseleave="{!c.onMouseLeft}">
ホバーするとポップオーバーが出るよ!
</a>
</span>
</lightning:layoutItem>
</lightning:layout>
</lightning:card>
</div>
</aura:component>
SimplePopoverExampleController.js
({
onMouseEntered: function(c, e, h) {
// 既に開いているポップオーバーがあれば、まず閉じる。
const popover = c.get("v.popover");
if (popover) popover.close();
// ポップオーバーのボディを作成する。
const parser = new DOMParser();
const popoverBody = parser.parseFromString("<div style=\"padding:16px;\">Hello World!</div>", "text/html").querySelector("body").firstChild;
// ポップオーバーにマウスホバーした時にポップオーバーを閉じたくないのでクローズ待ちタイマーを止める。
// ポップオーバーからマウスが離れたら、ポップオーバーを閉じる。
popoverBody.addEventListener("mouseenter", $A.getCallback(function(){
clearTimeout(c.get("v.closeTimer"));
}));
popoverBody.addEventListener("mouseleave", $A.getCallback(function(){
const popover = c.get("v.popover");
if (popover) popover.close();
}));
// ポップオーバーを表示する
const overlayLib = c.find("overlayLib");
overlayLib.showCustomPopover({
body: popoverBody, // ポップオーバーのボディ
referenceSelector: ".popoverReference", // ポップオーバーを表示する親要素のセレクタ
}).then(function (popover) {
c.set("v.popover", popover);
})
.catch(function(reason) {
console.error(reason);
});
},
onMouseLeft: function(c, e, h) {
// 親要素からマウスが離れた時は、ポップオーバーにホバーしていなければ閉じる。
// (ホバーした場合はクローズ待ちタイマーを止める)
c.set("v.closeTimer", setTimeout($A.getCallback(function(){
const popover = c.get("v.popover");
if (popover) popover.close();
}), 100));
},
})
SimplePopoverExample.css
.THIS .popoverReference {
padding-right: 1rem;
}
気になった点
表示されたポップオーバーの矢印が、ホバーした親要素に重なる(!マークが隠れてる)。
- マウスホバーの要素の上位にポップオーバーの参照要素を作成し、パディングで調整する。
padding-right: 1rem;
ポップオーバーのボディを動的に作成した場合、たまに矢印の位置がずれる
- 何回か表示/非表示を繰り返すと揃うようになるので、多分ポッポオーバーのボディの高さ確定とポップオーバーの位置算出のタイミングの問題。
- 高さを早く確定して上げる必要があるので、すべてのデータが揃ってからポップオーバーの描画を開始するのが良さそう。