12

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?

14

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();
  • This is the only solution that works! Thanks Laura – Mahat Hussein Apr 9 '18 at 9:42
  • Can't get this to work when calling notifyClose() from inside the then of a promise. Any suggestions? – Aequitas Aug 24 '18 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 Nov 27 '18 at 19:30
12

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.

  • 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 Mar 21 '18 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!! – Salesforce_Noobie Oct 18 '18 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." – AvailableName Jan 9 at 10:21
6

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();
  }
})
  • I belive salesforce documentation suggests a better approach. component.find("overlayLib").notifyClose(); developer.salesforce.com/docs/atlas.en-us.lightning.meta/… – Pranay Jaiswal Nov 16 '17 at 19:54
  • At the time of writing the answer, this did not work. Does it work for you, Pranay? – cottog Nov 24 '17 at 13:21
  • Works for me, probably they have updated docs. – Pranay Jaiswal Nov 28 '17 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. – P. Lapointe Jan 29 '18 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. – J. Lietzau Jul 30 at 20:14
4

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.

  • 1
    thanks for your help! It worked for me – Martin Larizzate Oct 21 at 19:43
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

  • 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. – cottog Sep 28 '17 at 7:33
  • I tested this on chrome winter 18 on my dev box too. Lemme test a bit more and get back – Rao Sep 28 '17 at 11:23
  • Hi, Rao! I updated my question with a solution where I added the overlayPanel to an attribute in the markup. – cottog Sep 28 '17 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 Sep 28 '17 at 11:33

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.