Arkady
Arkady

Reputation: 393

Programmatically create HTML list and show child elements on click

I am trying to build an HTML list from a JSON array where if a list object contains a child array of "levels" then clicking on the list item should reveal the levels as subsequent list items. The levels should be hidden by default until parent is clicked on (see below for graphic)

Please see my code attempt below

$('#menuList ul')
         .append(
             $('<li></li>')
                 .append(
                     $('<a></a>')
                         .attr('href', '#')
                         .click(function (e) {

                             if (result.levels) {
                                 //if child levels, show levels on parent click
                                 var thelevels = result.levels;
                                 thelevels.forEach(function (level) {
                                     console.log(level);
                                 });
                             }
                             // where I handle the click event
                             doStuff(el, this.text);
                             e.preventDefault();
                         })
                         .data('myName', result.name)
                         .data('myNumber', result.mynumber)
                         .text(result.name)
                 )
         );

Sample of data:

{
            "result_id": 7,
            "name": "My Name",
            "mynumber": "11",
            "levels": [
                0,
                1,
                2
            ]
        }

Mockup

enter image description here

Upvotes: 0

Views: 1280

Answers (1)

SciFiThief
SciFiThief

Reputation: 586

Based on your response you can do something like this:

// define construct table function, run through response and build table rows
// if there is levels, build levels, all in memory, not appended to DOM yet. 
function constructTable(response) { 
   var html = $("div"); // create div, but not append it yet to DOM

   for(var i = 0; i < response.length; i++) {
       var item =  response[i];

        var itemHtml = '<div class="item" data-id="' 
                + item.result_id
                + '">' 
                + '<p class="title">' 
                + item.name 
                + '</p>' 
                + '<div class="subItems">'
                + '</div>'
                + '</div>';

        var $itemHtml = $(itemHtml);

        if(item.levels.length) {
            for(var j = 0; j < item.levels.length; j++) {
               var subItem = item.levels[j];
               var subItemHtml = '<div class="subItem" data-id="' + subItem + '">' + "SubItem " + subItem + '</div>';

               $itemHtml.find('.subItems').append(subItemHtml);
           }
       }

       html.append($itemHtml);
   }
   return html;
}

var table = constructTable(response); // call function with response

$(".container").append(table); // append table to container at once, with all
// rows and sub items rendered.

// event for handling toggle of sub items.
$(".item").on("click", function() {
    $(this).find('.subItems').toggle();
});

Here is jsfiddle: http://jsfiddle.net/kdynfezw/6/

But you should look on Backbone and MarionetteJS and its CompositeView.

http://marionettejs.com/docs/v2.4.3/marionette.compositeview.html

It handles structure like this just well.

Upvotes: 2

Related Questions