[SalesForce] Is it possible for nested subcomponents to receive events from parent components in Lightning

Lets assume we have the following hierarchy of Lightning Components

<c:master>
    <c:sibling1 aura:id="sibling1" />
</c:master>

PART I

Is it possible for a child component (here sibling1) to handle an APPLICATION event registered in master's markup and fired in master's js-controller?

I have an issue with that, where I have the same handler in master and sibling1 declared, but only master is receiving (or handling) the event, but not sibling1.

Here is my code reduced to the basics

master.cmp

<aura:component controller="masterApex" implements="forceCommunity:availableForAllPageTypes,force:appHostable" >
    <aura:registerEvent   name="change"     type    ="c:changeEvent"/>
    <aura:handler         name="change"     event   ="c:changeEvent" action="{!c.handleChange}"/>
    <a><ui:outputText value="do it" click="{!c.fireTheChange}"/></a>
    <c:sibling1 aura:id="sibling1" />
</aura:component>

masterController.js

fireTheChange : function(component, event, helper) {
    console.log("fireTheChange");       
    var fireEvent = component.getEvent("change");
    fireEvent.fire();
},

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

sibling1.cmp

<aura:component controller="sibling1Apex" implements="forceCommunity:availableForAllPageTypes,force:appHostable" >
    <aura:handler         name="change"     event   ="c:changeEvent" action="{!c.handleChange}"/>
</aura:component>    

sibling1Controller.js

handleChange : function(component, event, helper) {
    console.log("____R_E_C_E_I_V_E_D____");
},

changeEvent.evt

<aura:event type="APPLICATION" >
</aura:event>

Now if i click on "do click" in the console.log I got only

fireTheChange
handleChange

but I'm missing

____R_E_C_E_I_V_E_D____  

PART II

To interact with nested child components, is there only the APPLICATION event? Would a COMPONENT event work, too? Are there other ways for master of interacting with sibling1 without events at all? I found that setting sibling1's attributes from master is easy in masterController.js

var sibling1 = component.find('sibling1');
sibling1.set("v.whateverAttributeName","aNiceValue");

Now is it also possible to execute siblings controller-methods and let it rerender from within masterController.js?

Or is there an other recommend pattern for that?

Best Answer

There is a lot going on in this post so I'll give you some thoughts but can't answer everything.

1. The preferred way for parent to child communication is to use <aura:method>. See https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cmp_methods.htm It should be a bit simpler than using events.

2. You declare changeEvent.evt as an application event but the syntax, component.getEvent("change"), is used for component events. Try $A.get("e.c:changeEvent") instead for an application event. See https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/events_application.htm

3. It's probably ok to use <aura:handler name="change" ..> but try name="somethingElse" instead in case there is some side effect of name="change", which is used in automatic change handlers. See https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/js_cb_data_change.htm.