10

I'm trying to handle the following task:

a component creates on the init-event a component dynamically

CREATOR COMPONENT

.cmp
<aura:handler name="someEvent" event="someEvent" action="{!c.someEventHandler}"/>

<aura:handler name="init" value="{!this}" action="{!c.createDetail}"/> {!v.body} </div>

.controller

createComp : function(component, event, helper){
        component.set("v.body", []);

        $A.createComponent(
            "c:someComp",
            {},
            function(newComp){
                var newCompBody = component.get("v.body");
                newCompBody.push(newComp);
                component.set("v.body", newCompBody);
            }
        );
},

someEventHandler : function(component, event, helper){
console.log("event caught");
}

This works just fine. A component event is fired in the component that got created dynamically. This event should be handled by the component that created the other component but its not working ... (console.log does not show up)

CREATED COMPONENT

.cmp
<aura:registerEvent name="someEvent" type="c:someEvent" />

.controller

// action for a button
someAction : function(component, event, helper){
        var someEvent = component.getEvent("someEvent");
        someEvent.fire();
        console.log("save event fired");
    }

Any suggestions?

Thanks!

5 Answers 5

8

Supporting @Menzman's solution, changing to an Application event in the interim will resolve this.

Once thing to watch out for however is to make sure you remove the name attributes from the handlers, otherwise they won't work.

So your handler would be:

<aura:handler event="someEvent" action="{!c.someEventHandler}"/>

And firing the event would look like:

// action for a button
someAction : function(component, event, helper){
    var someEvent = $A.get("e.c:someEvent");
    someEvent.fire();
    console.log("save event fired");
}

The event handler will remain unchanged.

5
  • 1
    This is fine, if you only have one instance but what if you have multiple instances and only want one of the instances to handle the event that was fired without the other instances picking it up? Commented Sep 21, 2016 at 2:05
  • Depending on the application structure, stopPropagation() could be used to prevent other components handling the same event if required. Commented Oct 26, 2016 at 14:56
  • Rather depressing that I just hit this - including having to remove the name - in March 2017.
    – Keith C
    Commented Mar 9, 2017 at 9:57
  • September, and still not fixed... Spent way too much time on this. Commented Sep 8, 2017 at 15:07
  • Ran into this as well. After several hours of trials finally found this thread. Thanks @ChrisWoolcott - for finding this bug and posting the answer.
    – Eric
    Commented Sep 22, 2017 at 14:08
7

Your code is not wiring up the someEventHandler action method during the create of someComponent.

The empty {} in the call to $A.createComponent() needs:

{
   someEvent: component.getReference("c.someEventHandler")
}

See https://developer.salesforce.com/docs/atlas.en-us.198.0.lightning.meta/lightning/js_cb_dynamic_cmp_async.htm for an example of how to do that.

10
  • Thanks for your answer. This will work if I know what function should be executed while creating the component. But if I just want to fire the event and some other component (not the next parent) in the hierarchy should catch it, it will not work out this way.
    – MS88
    Commented Jan 25, 2016 at 9:04
  • So the component will not be as loosely coupled as I want it to be ;)
    – MS88
    Commented Jan 25, 2016 at 9:05
  • That is a different question/scenario than the one you originally described "This event should be handled by the component that created the other component but its not working". It sounds like what you are looking for instead is event bubbling - see developer.salesforce.com/docs/atlas.en-us.lightning.meta/… for what you are looking for. NOTE: event bubbling support was a fairly recent addition to Lightning Components. Commented Jan 26, 2016 at 15:21
  • Unfortunately, this document does not mention anything about dynamic component creation and what this can cause here. And something like dynamically adding an event handler does not make sense to me too, because the handler already exists in the parent component ... am I still missing something here or is this simply not supported yet?
    – MS88
    Commented Jan 28, 2016 at 10:02
  • Event bubbling should work irregardless of how the component firing the event is created (via markup or $A.createComponent()). It is possible that you have run into a bug in event bubbling. I'm asking the team that owns this now. Commented Jan 28, 2016 at 13:12
2

(sorry I still can't write a comment so...)

@Marco S88: as workaround I used an application event (https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/events_application.htm).

The downside is that it is recommended to favor component events over application events and you can't have different names for the same event type - but in my situation an application event did the magic.

2

I ran into this issue, however, I found that when I un-rendered the child component and then re-rendered it the component event was being handled.

Which led me to think, the problem was the parent component declaring the handler before the child component is downloaded to the client and therefore not handling the event, but once the child component was closed and reopened, its markup was already downloaded by the client and the parent component's handler the firing of the event.

I added dependencies for the child component and event to the parent component's markup, and now the parent component is correctly handling the event.

Here is the updated code:

Parent.cmp

<aura:handler name="init" value="{!this}" action="{!c.handleInit}" />

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

<aura:method name="display" action="{!c.handleShowModal}">
    <aura:attribute name="attrs" type="Object" />
</aura:method>

<aura:dependency resource="markup://c:childCmp" />
<aura:dependency resource="markup://c:Callback" type="EVENT" />

ParentController.js

handleShowModal: function (component, event, helper) {
    var modalFooter;
    $A.createComponent(
        ["c:childCmp", {onsave: component.getReference('c.handleSave')}],
        function (content, status) {
            modalFooter = content;
            if (status === "SUCCESS") {
                component.find('overlayLib').showCustomModal({
                    footer: modalFooter,
                    cssClass: "slds-modal_medium"
                })
            }
        }
    );
},

handleSave: function (component, event, helper) {
    var selectedOpps = component.get('v.opportunities').filter(opp => {
        return opp.selected;
    });
    console.log(selectedOpps);
}

childCmp.cmp

<aura:registerEvent name="onsave" type="c:Callback" />

<lightning:button variant="brand" label="Save" onclick="{!c.handleSave}" />

ChildCmpController.js

handleSave: function (component, event, helper) {
    component.getEvent("onsave").fire();
},
0

(sorry I can't write a comment)

I can confirm that I have the same issue with this scenario:

When I hardcode/instantiate a certain component as part of a subcomponent like this:

<aura:component>
    <ul aura:id="listElementsContainer">

        <c:MyListElementComponent />

    </ul> 
</aura:component>

then an outer/more top level component can catch the event fired inside MyListElementComponent - but when I do the creation in the controller like this

    createListElements : function(component) 
    {
        var listElementsContainer = component.find("listElementsContainer");

        $A.createComponent(
        "c:MyListElementComponent", 
        {
            "data": someData
        }, 
        function(newComponent)
        {
            var bodyContainerArray = listElementsContainer.get("v.body");
            bodyContainerArray.push(newComponent);
            listElementsContainer.set("v.body", bodyContainerArray);
        });
    }

the event fired (I debugged the event is beeing fired) is never catched (handler did not change at all). Even when I inspect the DOM there is no obvious different between the "hardcoded" element and the "generated" element.

You must log in to answer this question.

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