Cameron
Cameron

Reputation: 28803

Build a menu from JSON

I'm attempting to build some dynamic menus that are created on the fly by calling a JSON request via jQuery to build the menu. I have the following planned menu structure:

<ul class="menu">
    <li>
        <a href="/Organisations/201/NewJournalEntry" title="New Journal Entry">
            <span class="icon journal-new">New Journal Entry</span>
        </a>
    </li>
    <li>
        <a href="/Organisations/201/People" title="View People">
            <span class="icon people">People</span>
        </a>
    </li>
    <li class="sep">
        <a href="/Organisations/201/Edit" title="Edit">
            <span class="icon edit">Edit</span>
        </a>
    </li>
</ul>

and the following JSON as an example:

{"menu": {
  "id": "organisation-201",
  "class": "menu",
  "content": {
    "menuitem": [
      {"text" : "New Journal Entry", "title" : "New Journal Entry", "href" : "/Organisations/201/NewJournalEntry", "liClass" : "", "icon" : "icon journal-new" },
      {"text" : "View People", "title" : "View People", "href" : "/Organisations/201/People", "liClass" : "", "icon" : "icon people" },
      {"text" : "Edit", "title" : "Edit", "href" : "/Organisations/201/Edit", "liClass" : "sep", "icon" : "icon edit" }
    ]
  }
}}

What would be the best way to do this? The url that would be queried would be something like '/MenuBuilder/organisation-201.json`

I have looked at the $.getJSON method, but is the correct thing to be looking at? Can anyone offer suggestions etc or even better examples.. Thanks

This is what I've tried so far...

$(document).ready(function() {

                // First we connect to the JSON file
                $.getJSON('menu.json', function(data)
                {
                    // Setup the items array
                    var items = [];
                    // For each line of data
                    $.each(data, function(key, val)
                    {
                        items.push('<li class="' + liClass + '"><a href="' + href + '"><span class="' + icon +'">' + text + '</span></a></li>');
                    });

                    $('<ul/>', {
                        html: items.join('')
                    }).appendTo('#buildHere');

                });

                // END json

            });

Upvotes: 1

Views: 8977

Answers (2)

mgibsonbr
mgibsonbr

Reputation: 22007

$.getJSON is really the way to go. The success callback will give you the data already as a JavaScript object, so you can write your code to turn it into DOM elements without worrying about converting it:

$.getJSON('/MenuBuilder/organisation-201.json',{},function(data) {
    var ul = $("<ul/>")
        .attr("id",data.menu.id)
        .addClass(data.menu.class);
    $.each(data.menu.content.menuitem, function() {
        var li = $("<li/>")
            .appendTo(ul)
            .addClass(this.liClass);
        var a = $("<a/>")
            .appendTo(li)
            ...
    });
});

Or, if creating the elements manually is too much work, you can look at some templating plugin like Rody van Sambeek suggested. Haven't used one yet, so I can't indicate any.

Note: my example above aimed at simplicity and readability, not efficiency. Usually it won't be a problem, but if it ends up too slow and you need to optimize, the recommended way of doing that is to mount a big string using Array.join and call $() on it once:

var html = ['<ul id="', data.menu.id, '" class="', data.menu.class, '">'];
// Keep adding elements to html as strings
// ...
html.push('</ul>');
var ul = $(html.join(''));

Upvotes: 1

Rody
Rody

Reputation: 2655

Yes, you can definitely use the $.getJSON method or the longhand $.ajax method from JQuery.

You should consider using some sort of templating mechanism to generate the menu from within javascript. You can use JSRender https://github.com/BorisMoore/jsrender or another JQuery templating engine.

I personally prefer KnockoutJS http://knockoutjs.com/ which has a build in templating engine. But it has much more to offer than just javascript templating.

Upvotes: 2

Related Questions