Best way to create nested HTML elements with jQuery [closed]

Solution 1:

write them as long string and than place them in the document using a suitable jQuery function. Something like:

The problem with this approach is that you'll need a multi-line string - something Javascript doesn't support - so in reality you'll end up with:

elem.html(
'<div class="wrapper">'+
    '<div class="inner">'+
        '<span>Some text<span>'+
    '</div>'+
    '<div class="inner">'+
        '<span>Other text<span>'+
    '</div>'+
'</div>');

Using the method you suggested above, this is about as clean as I could manage to get it:

elem.append(
    $('<div/>', {'class': 'wrapper'}).append(
        $('<div/>', {'class': 'inner'}).append(
            $('<span/>', {text: 'Some text'})
        )
    )
    .append(
        $('<div/>', {'class': 'inner'}).append(
            $('<span/>', {text: 'Other text'})
        )
    )
);

The other advantage to doing this is that you can (if desired) get direct references to each newly created element without having to re-query the DOM.

I like to write polyglots, so to make my code re-usuable I usually do something like this, (as jQuery's .html() doesn't support XML):

// Define shorthand utility method
$.extend({
    el: function(el, props) {
        var $el = $(document.createElement(el));
        $el.attr(props);
        return $el;
    }
});

elem.append(
    $.el('div', {'class': 'wrapper'}).append(
        $.el('div', {'class': 'inner'}).append(
            $.el('span').text('Some text')
        )
    )
    .append(
        $.el('div', {'class': 'inner'}).append(
            $.el('span').text('Other text')
        )
    )
);

This isn't very different to method #2 but it gives you more portable code and doesn't rely internally on innerHTML.

Solution 2:

I found this solution while I was researching something else. It's part of an "Introduction to jQuery" by the creator of jQuery and uses the end() function.

$("<li><a></a></li>") // li 
  .find("a") // a 
  .attr("href", "http://ejohn.org/") // a 
  .html("John Resig") // a 
  .end() // li 
  .appendTo("ul");

Applying to your question it would be ...

$("<div><span></span></div>") // div 
  .addClass("inner") // div 
  .find("span") // span 
  .html("whatever you want here.") // span 
  .end() // div 
  .appendTo( elem ); 

Solution 3:

I like the following approach myself:

$('<div>',{
  'class' : 'wrapper',
  'html': $('<div>',{
    'class' : 'inner',
    'html' : $('<span>').text('Some text')
  }).add($('<div>',{
    'class' : 'inner',
    'html' : $('<span>').text('Other text')
  }))
}).appendTo('body');

Alternatively, create your wrapper first, and keep adding to it:

var $wrapper = $('<div>',{
    'class':'wrapper'
}).appendTo('body');
$('<div>',{
    'class':'inner',
    'html':$('<span>').text('Some text')
}).appendTo($wrapper);
$('<div>',{
    'class':'inner',
    'html':$('<span>').text('Other text')
}).appendTo($wrapper);