Ember.js Recursive component and action bubble up

Quang Nguyen
Sep 3, 2018 · 2 min read

Ember recursive component is very interesting. I had to create a side tree view component for a project I was working on and I created it using a recursive component in Ember.

The cool thing with recursive components in Ember is that it helps you create tree structures in a very elegant and short way in terms of code.

For example, let’s say you created a tree data structure, something that looks like this:

let tree = [
{
id: 1,
children: [
{
id: 2,
children: []
}
]
},
{
id: 3,
children: []
}
]

And then you want to display this tree like a side menu. So we will have something like this:

// tree.hbs
<ul>
{{tree-recursive-component tree=tree}}
</ul>
// tree-recursive-component.hbs
<li>
// display tree id
{{tree.id}}
{{#each tree.children as |child|}}
<ul>
{{tree-recursive-component tree=child}}
</ul>
{{/each}}
</li>

Imagine writing that in a loop … ( you would have to do many many many nested loops which is nasty and looks very bad, definitely not good practice ).

So what happens now? You have create a tree like structure, you can style it so that for each <ul> element or child, you can indent it to make it look nicer. But to make it more interesting, lets pass an action to the component because we want to collapse and expand the lists items right?

For simplicity’s sake, lets say you pass an action that console.log the current item’s id. What you will soon find out is that whenever you click on an item in the list, depending on how deep you are in the recursive call ( or the levels at which you are in the tree / recursive call ), the number of console log calls will equal the current recursive call.

Why is this?

This is because actions inside recursive components bubbles up, meaning that if I am the fifth child in the recursive component, I will execute my action, but I have to travel up the stack and call each of my parent’s actions ( which have the same action as I am because we all share the same component ).

How do we remedy this? We need set the bubble attribute in the Ember’s action helper to false so that it wont call the actions on every parent component but its own, like so:

<ul {{action “printToConsole” bubbles=false}}>

This was a fun and challenging task that I had the pleasure of solving. I am glad that I stumbled across this problem because solving this helped me understand Ember better and become a better programmer overall.

quangtn0018

Just my findings and techniques that I’ve learned from working and doing side projects on all things software engineering related

Quang Nguyen

Written by

Software Engineer

quangtn0018

Just my findings and techniques that I’ve learned from working and doing side projects on all things software engineering related

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade