14

The documentation shows how to close an overlay immediately after showing the modal, however, this is not very useful for real-life situations.

I have a component which has a lightning:overlayLibrary in its markup. When a button is clicked, the controller fires a showCustomModal with a child component as its content. The child component has a button that fires an event when pushed. The parent component handles the event and should close/destroy the modal.

I've tried component.find('overlayLib').notifyClose() in the event handler, however, it seems that this fires an event that needs to be handled.

How would one go about handling this event or is there an easier way to do this?

5 Answers 5

15

I was having some trouble getting the notifyClose function to work as well. If you base your code off the samples here, you'll be tempted to use the same local ID for multiple lightning:overlayLibrary declarations. That doesn't seem to work reliably.

I found I had to do something like this:

in the parent component which will launch the modal:

<lightning:overlayLibrary aura:id="overlayLib1"/>

in that component's helper where showCustomModal is called

component.find('overlayLib1').showCustomModal({...

in the modal's component containing buttons which will trigger closing

<lightning:overlayLibrary aura:id="overlayLib"/>

in that component's helper's close function

component.find("overlayLib").notifyClose();
2
  • Can't get this to work when calling notifyClose() from inside the then of a promise. Any suggestions?
    – Aequitas
    Commented Aug 24, 2018 at 1:26
  • @Aequitas did you ever find a solution? I have a similar situation, since my modal does an asynch callout to an apex controller, and in the then of the promise returned from the controller I try to call notifyClose()
    – smohyee
    Commented Nov 27, 2018 at 19:30
15

Looks like previous answers no longer work. Here is the solution that worked for me. It seems that now you can close this modal only from a returned promise so we can save it and use later:

Add an attribute to a component with an overlay library

<aura:attribute name="modalPromise" type="Aura.Action"/>

Then save the returned promise to that attribute

var modalPromise = component.find('yourOverlayLibId').showCustomModal({ ... });
component.set("v.modalPromise", modalPromise);

And when you need to close your modal you can use the previously saved promise

component.get('v.modalPromise').then(
    function (modal) {
        modal.close();
    }
);

That's it. Don't forget that all that stuff is happening in the component containing <lightning:overlayLibrary> tag. So from the actual modal, you'll probably have to fire an event to trigger this flow.

3
  • It seems, if the overlay library is defined in the top level component, answer by @cottog is working. Otherwise this option seem to work. Not sure why though!
    – Ranga
    Commented Mar 21, 2018 at 14:55
  • This solution works for me. I think it is because the overlayLibrary is defined in the same component that is creating my popover window. Thanks for the solution!! Commented Oct 18, 2018 at 17:48
  • This is the correct solution, according to the docs. developer.salesforce.com/docs/component-library/bundle/… "showCustomModal() and showCustomPopover() return a promise, which is useful if you want to get a reference to the modal when it’s displayed." Commented Jan 9, 2019 at 10:21
7

Add the OverlayPanel to an attribute of type Aura.Component[] so that it could be reached from the JS controller.

Component

<aura:component>
    <aura:attribute name="overlayPanel" type="Aura.Component[] />
    <lightning:overlayLibrary aura:id="overlayLib"/>
    // body of component
</aura:component>

Controller

({
  showModal : function(cmp, evt, helper) {
    component.find('overlayLib').showCustomModal({
      //modal attributes
    }).then(function (overlay) {
      component.set('v.overlayPanel', overlay);
    });
  },
  handleOk : function(cmp, evt, helper {
    var overlayPanel = component.get('v.overlayPanel');
    overlayPanel[0].close();
  }
})
5
  • I belive salesforce documentation suggests a better approach. component.find("overlayLib").notifyClose(); developer.salesforce.com/docs/atlas.en-us.lightning.meta/… Commented Nov 16, 2017 at 19:54
  • At the time of writing the answer, this did not work. Does it work for you, Pranay? Commented Nov 24, 2017 at 13:21
  • Works for me, probably they have updated docs. Commented Nov 28, 2017 at 12:10
  • Is this still working for you @cottog? I tried to do the exact same thing with a reference to the handleOk function inside the modal and it doesn't work. It only works when I do it in the then function but storing it and calling the close function on the retrieved overlayPanel doesn't work on my side for some reason. Commented Jan 29, 2018 at 21:32
  • Can not get this to work. Debugging the output from component.get('v.overlayPanel') even gives me an object that looks like the customModal. I can call close() on it, but nothing happens. Commented Jul 30, 2019 at 20:14
5

If you want the ability to close the modal from itself, there's a way easier way doing this (for custom overlay comp.):

According the SF lightning comp. documentation you can declare another overlayLibrary on your custom overlay with the same aura:id on the parent comp. like this:

<lightning:overlayLibrary aura:id="overlayLib"/>

then, on your overlay component add this (as your button handler):

({
  handleCancel : function(component, event, helper) {
      //closes the modal or popover from the component
      component.find("overlayLib").notifyClose();
  },
})

Works like a charm.

0
0

I found a hacky way to do this. I used the exact same code from the documentation except the notifyClose() part. Clearly notifyClose() method does not seem to do the trick as you pointed out.

After looking around a lot I started thinking how would I close a popup in javascript and stumbled on the below link.Prior to this I was using window.close to close the popup and end up getting “Scripts may close only the windows that were opened by it” error. I tried to look around on how to counter this error and stumbled up on this below link.

https://stackoverflow.com/questions/35936011/chrome-scripts-may-close-only-the-windows-that-were-opened-by-it-error

Applying the same concept here:

({
    handleCancel : function(component, event, helper) {
        //closes the modal or popover from the component
        //cancel button will not work since notifyClose() does not work.
        component.find("overlayLib").notifyclose();
    },
    handleOK : function(component, event, helper) {
        var popup = window.open(location, '_self', '');
        popup.close();
    }
})

enter image description here

4
  • Hi, Rao! Thank you for your suggestion! I tried your code in a Partner Community and it refreshes the site, which kinda solves the problem, but I think our client will see it as a suboptimal solution. I also tried it in the internal lightning app, but there it closes the entire window. It looks good in your example GIF, do you have any idea why it doesn't work for me? I use Chrome and a Winter 18' sandbox. Commented Sep 28, 2017 at 7:33
  • I tested this on chrome winter 18 on my dev box too. Lemme test a bit more and get back
    – Rao
    Commented Sep 28, 2017 at 11:23
  • Hi, Rao! I updated my question with a solution where I added the overlayPanel to an attribute in the markup. Commented Sep 28, 2017 at 11:28
  • Awesome, can you post that as an answer and mark it resolved. This will help others who come here looking for a proper answer
    – Rao
    Commented Sep 28, 2017 at 11:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .