3

So, I set about implementing a Picklist component for the SDLS Picklist and am having a problem with propagation and firing of events.

For this, I created the top level picklist component (detail excluded for brevity) with an event handler to handle clicks on the list options:

<!-- picklist.cmp -->
<aura:component >
    <aura:attribute name="label" type="String" default=""/>

    <!-- when an option is clicked... -->
    <aura:handler name="onSelectPicklistOption" event="c:onSelectPicklistOptionEvent" action="{!c.handleSelectOption}"/> 

    <div aura:id="picklist" class="slds-picklist slds-dropdown-trigger slds-dropdown-trigger--click">
        <!-- detail excluded -->
        {!v.body}
    </div>    
</aura:component>

Note, I'm using an event so that I can call the parent method from the child component.

Then, the controller with handler:

({
    // wanting to fire onSelectPicklistOptionEvent
    handleSelectOption: function(component, event, helper) {
        console.log('handleSelectOption')
    }
})

Then, I created a picklistOption (child to picklist) component (again, unimportant detail excluded), registering the event and calling from the toggle function:

<!-- picklistOption.cmp -->
<aura:component >
    <!-- Picklist option selected -->
    <aura:registerEvent name="onSelectPicklistOption" type="c:onSelectPicklistOptionEvent"/>

    <li role="presentation">
        <span onclick="{!c.toggle}">
        </span>
    </li>
</aura:component>

the associated controller to call the parent picklist event...

({
    toggle : function(component, event, helper) {
        // select this one and de-select the others
        var selectOptionEvent = component.getEvent("onSelectPicklistOption");
        selectOptionEvent.setParams({
            "option": component
        });
        selectOptionEvent.fire();

        // also tried $A.get('e.c:onSelectPicklistOptionEvent')
    }
})

And finally, I create my picklist in my layout component, setting the body of the picklist as picklistOption's:

<!-- layout.cmp -->
<aura:component>
    <c:picklist label="Pick an option">
        <c:picklistOption text="test0" label="Test0"/>
        <c:picklistOption text="test1" label="Test1"/>
    </c:picklist>
</aura:component>

Sadly, the picklist handleSelectOption does not get called. This seems to be because the event handler is declared in the picklist component but the picklistOption's are basically declared in the layout component. I can fix this by putting my aura:handler in the layout component but that doesn't seem right to me since picklist is no longer encapsulated.

Am I missing the point on how to nest child components within its parent and thus causing this issue?

Thanks!

6

After some digging, I found that you need to declare your handler with the includeFacets="true" attribute, found in this document.

So, the picklist component becomes:

<!-- picklistOption.cmp -->
<aura:component >
    <!-- Picklist option selected -->
    <aura:registerEvent name="onSelectPicklistOption" type="c:onSelectPicklistOptionEvent" 
        includeFacets="true"/>

    <li role="presentation">
        <span onclick="{!c.toggle}">
        </span>
    </li>
</aura:component>

See this excerpt from the documentation:

Propagation to All Container Components

The default behavior doesn’t allow an event to be handled by every parent in the containment hierarchy. Some components contain other components but aren’t the owner of those components. These components are known as container components. In the example, c:container is a container component because it’s not the owner for c:eventSource. By default, c:container can’t handle events fired by c:eventSource.

A container component has a facet attribute whose type is Aura.Component[], such as the default body attribute. The container component includes those components in its definition using an expression, such as {!v.body}. The container component isn’t the owner of the components rendered with that expression.

To allow a container component to handle the event, add includeFacets="true" to the tag of the container component. For example, adding includeFacets="true" to the handler in the container component, c:container, enables it to handle the component event bubbled from c:eventSource.

  • 1
    Thank you for the answer, it really helped me out tonight. However, the includeFacets attribute should be on aura:handler, not aura:registerEvent. – smukov Nov 19 '17 at 19:05

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.