BlazeJS - How to display content recursively from a JSON in the template

Hi,

I create a simple form to manage some categories in my app…

I store it in the DB, and each category has :
parent
_id
title
description

From a template helper I fetch the content and get a JSON.

var categories = [{"_id":"krbGgiYAhRYscd64e","title":"root","description":"root description","parent":"0","createdAt":"2017-12-16T10:27:22.770Z","children":[{"_id":"3CzE4ryWWmoiL8hny","title":"Category 1","description":"Category 1 description","parent":"krbGgiYAhRYscd64e","createdAt":"2017-12-16T10:27:41.889Z","children":[{"_id":"nDPkQQT3b2zPBM55J","title":"SubCategory 1","description":"SubCategory 1 description","parent":"3CzE4ryWWmoiL8hny","createdAt":"2017-12-16T10:28:40.501Z"}]},{"_id":"AbAHLw3BXZ9LZ7ukJ","title":"Category 2","description":"Category 2 description","parent":"krbGgiYAhRYscd64e","createdAt":"2017-12-16T10:28:12.216Z","children":[{"_id":"trj2iZhA5vnk5dGzK","title":"SubCategory 2","description":"SubCategory 2 description","parent":"AbAHLw3BXZ9LZ7ukJ","createdAt":"2017-12-16T10:29:18.456Z"}]}]},{"_id":"3CzE4ryWWmoiL8hny","title":"Category 1","description":"Category 1 description","parent":"krbGgiYAhRYscd64e","createdAt":"2017-12-16T10:27:41.889Z","children":[{"_id":"nDPkQQT3b2zPBM55J","title":"SubCategory 1","description":"SubCategory 1 description","parent":"3CzE4ryWWmoiL8hny","createdAt":"2017-12-16T10:28:40.501Z"}]},{"_id":"AbAHLw3BXZ9LZ7ukJ","title":"Category 2","description":"Category 2 description","parent":"krbGgiYAhRYscd64e","createdAt":"2017-12-16T10:28:12.216Z","children":[{"_id":"trj2iZhA5vnk5dGzK","title":"SubCategory 2","description":"SubCategory 2 description","parent":"AbAHLw3BXZ9LZ7ukJ","createdAt":"2017-12-16T10:29:18.456Z"}]},{"_id":"nDPkQQT3b2zPBM55J","title":"SubCategory 1","description":"SubCategory 1 description","parent":"3CzE4ryWWmoiL8hny","createdAt":"2017-12-16T10:28:40.501Z"},{"_id":"trj2iZhA5vnk5dGzK","title":"SubCategory 2","description":"SubCategory 2 description","parent":"AbAHLw3BXZ9LZ7ukJ","createdAt":"2017-12-16T10:29:18.456Z"}]

Then I convert it to got a tree like

var categories = [ {
    "_id":"krbGgiYAhRYscd64e",
    "title":"root",
    "description":"root description",
    "parent":"0",
    "createdAt":"2017-12-16T10:27:22.770Z",
    "children":[ {
        "_id":"3CzE4ryWWmoiL8hny",
        "title":"Category 1",
        "description":"Category 1 description",
        "parent":"krbGgiYAhRYscd64e",
        "createdAt":"2017-12-16T10:27:41.889Z",
        "children":[ {
            "_id": "nDPkQQT3b2zPBM55J", "title": "SubCategory 1", "description": "SubCategory 1 description", "parent": "3CzE4ryWWmoiL8hny", "createdAt": "2017-12-16T10:28:40.501Z"
        }
        ]
    }
    ,
    {
        "_id":"AbAHLw3BXZ9LZ7ukJ",
        "title":"Category 2",
        "description":"Category 2 description",
        "parent":"krbGgiYAhRYscd64e",
        "createdAt":"2017-12-16T10:28:12.216Z",
        "children":[ {
            "_id": "trj2iZhA5vnk5dGzK", "title": "SubCategory 2", "description": "SubCategory 2 description", "parent": "AbAHLw3BXZ9LZ7ukJ", "createdAt": "2017-12-16T10:29:18.456Z"
        }
        ]
    }
    ]
}

]

Now, I would like to display a menu in my app from this…

So I did this :

    <div class="test">
    <ul>
         {{#each cat in allCats}}
         
            {{#if cat.parent = "root"}}
                <li>{{cat.title}}</li>
            
                <ul>
                    {{#each subcat in cat.children}}
                    <li>{{subcat.title}}

                        <ul>
                            {{#each subsubcat in subcat.children}}
                                <li> {{subsubcat.title}} </li>

                                <ul>
                                    {{#each subsubsubcat in subsubcat.children}}
                                        <li> {{subsubsubcat.title}} </li>
                                    {{/each}}
                                </ul>

                             {{/each}}

                        </ul>

                    </li>
                    {{/each}}
                </ul>
            {{/if}}


         {{/each}}
    </ul>

    </div>

And it work pretty well… But for each level of my tree, I have to add it manually…

What I would like is to be able to show all categories and subcategories recursivly without to have to add a level because I don’t want a limit for it.

But I’m not sure if it’s possible with blaze “each”, “if” or something else from the template ?

In the same way I need to create a select item


    <select name="categories" id="categories">
        <option value="id">Categorie 1 </option>
        <option value="id">--Categorie 1 -1 </option>
        <option value="id">--Categorie 1 - 2 </option>
        <option value="id">----Categorie 1 - 2 - 1 </option>
        <option value="id">Categorie 2 </option>
        <option value="id">Categorie 3 </option>
    </select>

All ideas are welcome.

thank’s

Mike

I’d try pulling in the data from your subscription as is but in your helper before you return it to the template you recursively transform it returning a standard menu data structure you can paint to the glass easily with blaze.

Haven’t used Blaze in a while, but what you need to do is invoke the template inside itself, something like this:

json.html

{{#each val, key in object}}
  {{#if _.isObject(val)}}
    <div>{{key}}:{{>json val}}</div>
  {{else}}
    <div>{{key}}:{{val}}</div>
  {{/if}}
{{/each}}

(Although this was assuming the data was a deep object, not collection items)

good luck using a standard JS exp (with lodash) inside the template without a helper :smiley: used too much React or did I miss some blaze update in the last months/years? :smiley:

It was just as an example, but I think you can add underscore/lodash to Blaze like this:

Template.registerHelper('_', () => _)

There’s a good explanation with code samples here:

http://meteorpedia.com/read/Trees

1 Like

Ha, I forgot that even existed. It used to my go to resource back in the day. One of the best contributions to our community from @gadicc among many others of course.

1 Like

hey wow thanks @robfallows and @serkandurusoy, great getting mentions after so much time :slight_smile: best wishes :slight_smile:

2 Likes

Thank’s guys

Your comments helped me to understand how to create a loop and pass variable :slight_smile:
In fact , no need to use a JSON with children.

  1. I create a helper to got the categories collection.
  2. With another helper I tested if the item is the root
  3. Then I call a template which take as variable the current category _id which will got the next categories which has this _id as parent… ( so root)
  4. Then from this template I call this same template and replace the variable with the new current _id of the category.
1 Like