Is it possible to have recursive components?


#1

I was trying to make a recursive component, following the recommendation to prepare for Ember 2.0, and I found this comment from Re-render compiled Ember templates:

I also followed the ideas behind a tutorial to implement a tree.

Yet, I have been unable to make a working recursive component. So I want to ask, is it possible at all today? It seems like Ember simply ends up in an infinite recursion parsing the templates or something like that. There are no building errors, but when I load the route with the recursive component the app freezes and shows no rendered views for that component.

This is my minimal example:

models/row.js

import DS from 'ember-data';

export default DS.Model.extend({
  description: DS.attr("string"),
  branches: DS.hasMany('row')
})

components/structure-row.js

import Ember from 'ember';

export default Ember.Component.extend({
  tagName: 'li',
  classNames: 'structure-row',
  initComponent: function(){
    var brancheslen = this.get('row').get('branches.length');
    this.set('explore', (brancheslen > 0));
  }.on('didInsertElement')
});

templates/component/structure-row.js

{{row.description}}

{{#if explore}}
  <ol class="structure wow">
  {{#each branch in row.branches}}
    {{#structure-row row=branch}}{{/structure-row}}
  {{/each}}
  </ol>
{{/if}}

I have tried many things. I’m even computing a explore variable in case the row.branches doesn’t yield a correct conditional (which doesn’t make much sense to me). The models are loaded correctly and the relationships are correct as well.


#2

Can you make a JSBin that shows what you’re trying to do? I’ll be happy to take a look at it.


#3

Thanks, here’s a JSBin that illustrates what I’m trying to do. However, I’m using the embedded records mixin for the RESTAdapter, and couldn’t replicate that behavior with fixtures in this example.


#4

After reading this thread: Changing tagName for a component I thought the reason why my component gets stuck in an infinite recursion might be because ember tries to render the templates before the data is there, thus it cannot check whether it should keep calling the component or not. Is that true?


#5

@jorge_lainfiesta here is a working version of recursive Ember component http://jsbin.com/jirubu/16

I took all of the Ember Data stuff out because it’s confusing to debug when there are so many layers of complexity. You can use this as a starting point and add complexity from here.


#6

Oh wow thanks a lot! That’s just what I needed. Seriously, thanks! I’ve been trying to make a recursive component for more than a week.


#7

You’re welcome. JSBin is great because it forces you to remove all of the complexity to get to the root of the problem.


#8

After some testing I found out it was not the an issue with the component that makes the recursion fail. It seems to be related to ember-data. My guess is that it does not assert the data correctly and thus falls into an infinite recursion. I’ll try to see what else to do.


#9

Hello People,

I am able to render the recursive component but while adding event listeners its behaving weird that the component which is called in the inner levels called multiple times. How to prevent this problem?


#10

The code snippet looks like this:

{{item.value}}
{{#if item.children.length}}
    {{#each item.children as |item|}} {{app-filter-new/app-filter-item item=item onToggleInclude=(action 'onToggleInclude') onItemClick=(action "onItemClick") }} {{/each}}
{{/if}}