[SalesForce] Lightning overlayLibrary function reference won’t close modal

Using the overlayLibrary, I am having quite a headache to nicely bind the footer's buttons functions with a parents function and closing the modal.

What I currently have which work fine except it doesn't ever close the modal look like this :

Parent component

<aura:component>
<lightning:overlayLibrary aura:id="overlayLib" />
<aura:attribute name="overlay" type="Aura.Component" />

<aura:attribute name="currentObject" type="Object" />

<lightning:button label="New Object" onclick="{!c.click_NewObject}" />
</aura:component>

Parent Controller

({
    click_NewEvaluation: function (cmp, event, helper) {
        var newObject = {};
        cmp.set('v.currentObject', newObject);

        var modalBody, modalFooter;
        $A.createComponents([
            ['c:modalBody', { 'currentObject': cmp.getReference('v.currentObject') }],
            ['c:modalFooter', { 'saveFunction': cmp.getReference('c.callback_SaveFunction') }],
        ],
            function (components, status) {
                if (status === 'SUCCESS') {
                    modalBody = components[0];
                    modalFooter = components[1];

                    cmp.find('overlayLib').showCustomModal({
                        header: 'New Object',
                        body: modalBody,
                        footer: modalFooter,
                        showCloseButton: true
                    }).then(function (overlay) {
                        cmp.set('v.overlay', overlay);
                    });
                }
            }
        );
    },

    callback_SaveFunction: function (cmp, event, helper) {
        //Both command do not work.
        cmp.find('overlayLib').notifyClose();
        cmp.get('v.overlay').close();

        //This function simply uses the v.currentObject and 
        //save it and it works perfectly once called by the saveFunction.
        helper.saveObjects(cmp, helper);
    }
})

Modal Footer

<aura:component >
    <lightning:overlayLibrary aura:id="overlayLib" />
    <aura:attribute name="saveFunction" type="Aura.Action" />

    <lightning:button name="cancel" label="Cancel" onclick="{!c.handleCancel}" />
    <lightning:button name="save" label="Save" onclick="{!v.saveFunction}" />
</aura:component>

If I use the notifyClose function directly in the footer, it works fine as expected. If I use the close function on the overaly promise directly after the modal open, it works fine but once it is stored in the overlay attribute, I cannot make it work outside of the .then function scope.

I tried to use component events fired from the footer but it didn't work and I felt like I was going down a messy path. I feel like there's something rather simple I am missing as everything works perfectly and logically except closing the modal part.

Anybody has any insight on what might be going wrong or has come across example that deal with this? What I've found online is extremely simple and explaining the structure which already works but nothing a complex to work on.

Edit: The following answer actually provide a solution which can close the modal window by doing :

var popup = window.open(location, '_self', '');
popup.close();

I still think that this should not be done however and that there is a way to simply use the library functions in order to cleanly achieve this so I will leave the question open.

Edit 2: Debugging the notifyClose() function shows that the following warning is logged by the aura framework:

"There is no event definition for event 'notify', probably because there is no component to handling it."

So it seems the simply calling the notifyClose() function from the component that created the modal doesn't work because the required event it is firing is not registered. Adding the event manually is not an option either and I am not sure if that method would be the right one or if this is an unintended bug (or my code just has something missing, but I tried again with the most minimal implementation and I keep running into the same problem).

Edit 3: Debugging the close function that is called on the OverlayPanel object (returned by the promise when creating the modal) return a similar error:

"Access Check Failed! Component.method():'markup://ui:close' is not visible to 'markup://c:Parent_component {117:0}'."

That one, I am not sure what it means but I'll concentrate on that. It just seems that the method cannot be accessed and it has a weird feeling of something the Locker Service would do.

Best Answer

It can be done via method on footer component.

You will need to save footer component as attribute in parent component.

Parent markup:

<aura:attribute name="footerCmp" type="Aura.Component"/>

When creating components, add following line in $A.createComponents callback:

cmp.set('v.footerCmp', components[1]);

Define a method in your footer component:

<aura:method name="closeModal" action="{!c.close}" />

And in footer component controller add "close" handler

close: function(component, event, helper) {
    component.find("overlayLib").notifyClose();
}

Now you can call "closeModal" method from callback_SaveFunction in your parent component like this:

cmp.get("v.footerCmp").closeModal();