7

Let's say that we have parentExpr and childExpr components. This is the markup of the parentExpr component:

<!--c:parentExpr-->
<aura:component>
   <aura:attribute name="parentAttr" type="String" default="parent attribute"/>

   <c:childExpr parentAttr="{!v.parentAttr}" />

</aura:component>

As you can see, I am passing value of parentAttr attribute to childExpr component. Now imagine that inside childExpr component, there is a grandChildExpr component where I have to pass this same value.

<grandChildExpr parentAttr="{!v.parentAttr}" />

If the components that need this attribute value are 10 steps deep, this can become tedious, tiring, and error prone. Also it is possible that childExpr component has no need of the attribute value, but it has to receive it in order for it to get down the tree. This is exactly what I want to avoid.

How should I go ahead, or what is the best approach in Salesforce Lightning to resolve this issue?

EDIT: Those who have worked in React might recall this situation, for which they use Context API or Redux.

  • I've struggled with this too and did not find a good solution so will be interested in the answers you get. – Keith C Aug 5 '18 at 8:37
  • Why not use events here? – Lightning Evangelist Aug 5 '18 at 18:54
3

Direct Answer


For all non-trivial cases where this might be an issue, you could consider using an abstract component, which resolves the issue of having to define the same attribute every time:

<!-- baseTemplate -->
<aura:component abstract="true">
  <aura:attribute name="someAttr" type="String" />
</aura:component>

<!-- parent -->
<aura:component extends="c:baseTemplate">
  Parent is here.
  <c:child someAttr="{!v.someAttr}" />
</aura:component>

<!-- child -->
<aura:component extends="c:baseTemplate">
  Child is here.
  <c:grandchild someAttr="{!v.someAttr}" />
</aura:component>

<!-- grandchild -->
<aura:component extends="c:baseTemplate">
  {!v.someAttr}
</aura:component>

However...


Frame Challenge


You shouldn't be designing your components in a way where this becomes necessary. Doing so is not only error-prone and tedious, it can have serious performance implications as aura:valueChange events have to propagate through a bunch of components that "don't care" about the value, except that they need to pass the buck on to the next child component that needs the value.

You'll notice that in all of the built-in components, they're all just one or two layers deep but can be mixed and matched in a variety of useful ways. It would be more practical to have a scenario like this:

<!-- parent -->
<aura:component>
   Parent is here.
   <hr />
   {!v.body}
</aura:component>

<!-- child -->
<aura:component>
  Child is here.
  <hr />
  {!v.body}
</aura:component>

<!-- grandchild -->
<aura:component>
  <aura:attribute name="myValue" type="String" />
  {!v.myValue}
</aura:component>

At which point, when you're composing your code, you'd write:

<aura:attribute name="outputText" type="String" default="Hello World" />
<c:parent>
  <c:child>
    <c:grandchild myValue="{!v.outputText}" />
  </c:child>
</c:parent>

From my understanding, this is how we're supposed to be using components. Single- or double-layer components that we can arrange in various ways when we need them. If need be, you can even write components that abstract away all the extra layers so you can take advantage of the above format. There's simply not much of an advantage of passing attributes through multiple layers.

  • On the number of layers, my view is that components and classes are somewhat equivalent, and when solving a complex problem many layers of classes are usually involved. – Keith C Aug 5 '18 at 8:39

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.