3

I created a component that displays a list of related records. When the user hovers over a record, a popover is opened showing a preview of the record using the lightning:overlayLibrary component. The popovers auto closes if you mouse over another record. It all works great except if I add a focusable element (e.g. a button to close the popover). For some reason this causes the window to scroll to the top if I move my mouse over 2-3 records. The popovers open/close correctly but the user will be randomly taken back to the top of the page if they've scrolled down.

I don't set the focus at all in my code so I don't know why this is happening.

The lightning design system documentation around popovers even states a focusable element is required.

Has anyone else run into this before?

Update Here's the snippet of code for showing/hiding the popovers:

showPopoverHelper : function(component, event){
    this.hidePopoverHelper(component, event); // close any open popovers
// get content for popover
    var index = event.target.attributes.getNamedItem('data-index').value;
    var suggestedArticles = component.get('v.suggestedArticles');
    var attributes = {"article": suggestedArticles[index]};

    $A.createComponent('c:ArticlePreview', attributes, function(newComp, status, errorMessage){
        if(status === "SUCCESS"){
            component.find('overlayLib').showCustomPopover({
                body: newComp,
                referenceSelector: '#' + event.target.attributes.getNamedItem('id').value,
                cssClass: "slds-popover,cKnowledgeOne",
            }).then(function (overlay) {
                var popoverList = component.get('v.popoverInstance');
                popoverList.push(overlay); // add popover instance to array
                component.set('v.popoverInstance', popoverList);
            });
        }
        else{
            console.log('error: ' + errorMessage);
        }
    });
},

hidePopoverHelper : function(component, event){
    var popoverList = component.get('v.popoverInstance');

    if(popoverList != null){
        for(var index in popoverList){ // close all popovers in array
            var popover = popoverList[index];
            if(popover != null){
                popover.close();
            }
        }
    }

    clearTimeout(component.get('v.hoverTimer'));
    component.set('v.hoverTimer', null);
},
1

We had quite similar issue with popovers.


Background:

Had a attribute to store the reference of overlay:

<aura:attribute name="overlay" type="Aura.Component[]" />

overlay is set in the promise:

component.find('overlayLib').showCustomPopover({
    // pop over body
}).then(function (overlay) {
    component.set('v.overlay',overlay);
}

Did following to close the popover:

var overlay = component.get("v.overlay")[0];
overlay.close();

Took sometime to find that overlay.close method looked like this:

close(shouldReturnFocus) {
    return new Promise(resolve => {
        this._panelInstance.close(() => {
            resolve();
        }, shouldReturnFocus);
    });
}

So after some trial and error the solution was to not pass 0 in the parameter. Luckily we also had added documented this:

// passing `0` to close is an undocumented feature about returning focus. 
// It prevents the page to scroll to the top.
overlay.close(0); 
  • Thanks for the suggestion. I wasn't sending a 0 before and, unfortunately, including a 0 didn't fix the issue – Danny Singh Sep 28 '18 at 13:16
  • Could you share a minimal version of code which could help us in replicating the issue? – Raul Sep 28 '18 at 13:32
  • Code snippet added to original post – Danny Singh Sep 28 '18 at 15:26
1

Turns out there is a bug in the way the overlay library closes popovers. The issue disappears if you use hide() instead of close() as close() destroys the popover and randomly returns focus to the top of the screen. Hide does not have this issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.