Ivor Ivor - 8 months ago 33
JSON Question

Object to nested unordered list with jQuery

I've been trying to convert this object to an unordered list, but I need to consolidate it in categories.

var snippets = [
{title: 'snippet 1', content: 'hello there 1', category: 'javascript'},
{title: 'snippet 2 ', content: 'hello there 2', category: 'wordpress'},
{title: 'snippet 3', content: 'hello there 3', category: 'javascript'},
{title: 'snippet 4', content: 'hello there 4', category: 'general'},
{title: 'snippet 5', content: 'hello there 5', category: 'general'}
];


The expected output is:

<ul>
<li>javascript
<ul>
<li>snippet 1</li>
<li>snippet 2</li>
</ul>
</li>
<li>wordpress
<ul>
<li>snippet 1</li>
<li>snippet 2</li>
</ul>
</li>
</ul>


I've been trying to do it with
$.each
, but for the love of me I can't get my head around it. I'm willing to use UnderscoreJS too.

$('body').append('<ul class="categories"></ul>');

$.each(snippets, function(i, v) {
var data = '<li class="category">'+ v.category +' ';
data += '<ul class="item"> <li> ' + v.title + ' </li> </ul>';
data += '</li>';

$(data).appendTo('.categories');
});


Output not expected:

<ul class="categories">
<li class="category">javascript
<ul class="item">
<li> snippet 1 </li>
</ul></li>
<li class="category">wordpress
<ul class="item">
<li> snippet 2 </li>
</ul>
</li>
<li class="category">javascript
<ul class="item">
<li> snippet 3 </li>
</ul>
</li>
<li class="category">general
<ul class="item">
<li> snippet 4
</li>
</ul>
</li>
<li class="category">general
<ul class="item">
<li> snippet 5
</li>
</ul>
</li>
</ul>


Can anyone give me a hint?

Answer Source

Description inline as comments:

var snippets = [
  {title: 'snippet 1', content: 'hello there 1', category: 'javascript'},
  {title: 'snippet 2 ', content: 'hello there 2', category: 'wordpress'},
  {title: 'snippet 3', content: 'hello there 3', category: 'javascript'},
  {title: 'snippet 4', content: 'hello there 4', category: 'general'},
  {title: 'snippet 5', content: 'hello there 5', category: 'general'}
];

// Create the UL that will contain all the categories
var ul = $("<ul>").addClass("categories");
// Use an object as a map of category to sublist
var lists = Object.create(null);
// Loop through the snippets
snippets.forEach(function(snippet) {
  // Get the sublist for this category
  var list = lists[snippet.category];
  if (!list) {
    // Don't have one yet, create it
    list = lists[snippet.category] = $("<ul>");
    // Create the item that will contain it in the main list
    var item = $("<li>").addClass("category").text(snippet.category);
    // Add the sublist to the item, and the item to the main list
    item.append(list);
    ul.append(item);
  }
  // Add this entry to the sublist
  list.append($("<li>").addClass("item").text(snippet.title));
});
// Done building, add the main list to the doc
ul.appendTo(document.body);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>