[SalesForce] Make a lightning component attribute available to children

I have a component that's really just a container. I'd like to be able to set an attribute on the container and have that attribute be able to passthrough anything I put inside the container without the user of the component having to pass it through.

ex: container

<aura:component>
  <aura:attribute name="att" type="string" default="true"/>
  <div>{!v.body}</div>
</aura:component>

ex: containee, a component that can go in the container

<aura:component>
  <aura:attribute name="attOffParent" type="string" default="true"/>
  <div>hi, {!attOffParent}</div>
</aura:component>

ex: implementation

<c:container att="foo">
  <c:containee/>
</c:container/>

obviously, I could pass in like <containee attOffParent="{!v.att}"/>

But is there a way to make it generally available to all the containees whenever they feel like using it, especially if they are a grandchild of the container and inside another component?

Open to ugly hacks, including going up the dom tree, using lightning events, etc.

Best Answer

Stick with passing the attribute value through to the child and grandchildren.

You could do something with an event firing in the parent to update attributes on the child and grandchild components, but it certainly wouldn't reduce complexity since you need to add the handlers in your components, it requires javascript in the controllers to fire and handle the events, and then of course there are the events themselves.

There are certainly use cases for that type of architecture, but keep in mind that when passing an attribute through to the controller it is automatically updated when changed in the parent, so the value that you are seeing is the current value in the parent, and not just a snapshot of what the value was when the component was rendered. You could create an application event that essentially recreates that functionality, but it is unnecessarily complex if this is all that you want to do.

Of course application events are certainly powerful tools, and there are instances where they your best/only option. It can be hard to make a general statement of when to use what, but if the following pattern works, anything else will likely just complicate matters:

<!-- The App -->
<aura:application >
    <aura:attribute name="att" type="Object" />
    <NameSpace:ChildComponent parentatt="{!v.att}" />
</aura:application>

<!-- ChildComponent -->
<aura:component>
    <aura:attribute name="parentatt" type="Object" />
    <NameSpace:GrandChildComponent grandparentatt="{!v.parentatt}" />
</aura:component>

<!-- GrandChildComponent -->
<aura:component>
    <aura:attribute name="grandparentatt" type="Object" />
</aura:component>