2

I need to build HTML from an jQuery ajax response. I don't like nesting ugly strings in javascript and I don't want to use mustache or any other templating script.

So I went for the approach of having a template HTML with display: none like the following:

<div id="message-template" class="message-tile" style="display: none;">
    <div class="profile-thumb"><img src="{{thumb-url}}" width="48" height="48" alt="{{person-name}}" /></div>
    <div class="message-data">
        <div class="message-info">
            <div class="sender-name">
                <a href="{{person-url}}">{{person-name}}</a>
            </div>
            <div class="posted-to">
                To <a href="{{posted-to-url}}">{{posted-to-title}}</a>
            </div>
        </div>
        <div>{{message-body}}</div>
    </div>
</div>

I want to be able to replace the strings between {{ }} with the actual values from the json object. Suppose this is the function that gets called on the jQuery.ajax onSuccess event:

function createNewElement(jsonObj) {
    var $clone = $('#message-template').clone();
    $clone.replaceString("{{person-name}}", jsonObj.personName);
    $clone.replaceString("{{thumb-url}}", jsonObj.thumbUrl);
    $clone.replaceString("{{person-url}}", jsonObj.personUrl);
    // etc
    $("#target-container").append($clone);
}

I invented the replaceString method, but is there something similar? Or do I need to traverse through each element child using find() ?

empz
  • 11,509
  • 16
  • 65
  • 106

3 Answers3

5

Actually you can use <script type = "text/template"> to create your own templates, this way it won't render on your page:

<script id="message-template" type = "text/template">

    <div class="message-tile" style="display: none;">
        <div class="profile-thumb"><img src="{{thumb-url}}" width="48" height="48" alt="{{person-name}}" /></div>
        <div class="message-data">
            <div class="message-info">
                <div class="sender-name">
                    <a href="{{person-url}}">{{person-name}}</a>
                </div>
                <div class="posted-to">
                    To <a href="{{posted-to-url}}">{{posted-to-title}}</a>
                </div>
            </div>
            <div>{{message-body}}</div>
        </div>
    </div>

</script>

Here's how you substitute your values:

function createNewElement(jsonObj) {
    var $clone = $('#message-template').html();
    $clone = $clone.replace("{{person-name}}", jsonObj.personName)
                   .replace("{{thumb-url}}", jsonObj.thumbUrl)
                   .replace("{{person-url}}", jsonObj.personUrl);
    // etc
    $("#target-container").append($clone);
}
Wilmer
  • 2,511
  • 1
  • 14
  • 8
  • 1
    Excellent! I didn't know what a script of type="text/template" was. Pretty elegant solution. Just one more question. Is there a .replaceAll because I have more than 1 occurrence of {{person-name}} – empz Mar 16 '14 at 22:09
  • No, but I found [this](http://stackoverflow.com/questions/5069464/replace-multiple-strings-at-once) here on SO or you maybe can implement your own. :p – Wilmer Mar 16 '14 at 23:39
1

There is a replace() method that can accept a regex, which would make it much more flexible.

Something like this would do it...

html.replace(/\{\{([^}]+)\}\}/g, function(all, key) {                   
                return jsonObj[key] || all;
            });

That way, {{personName}} would get the value from jsonObj.personName.

alex
  • 479,566
  • 201
  • 878
  • 984
  • Using the regex to replace the value by the corresponding key is a really interesting solution. Is there a format other than {{x}} that can make the regex simpler to replace {{x}} with obj.x? Maybe #[x]# or something – TKoL Jan 27 '15 at 08:20
  • @TKoL Indeed you could do that, though you'd still need to escape the brackets. Double braces are pretty common in templating languages. – alex Jan 27 '15 at 22:19
1
function createNewElement(jsonObj) {
    var $clone = $('#message-template').clone();
    $clone.html($clone.html().replace("{{person-name}}", jsonObj.personName));
    $clone.html($clone.html().replace("{{thumb-url}}", jsonObj.thumbUrl));
    $clone.html($clone.html().replace("{{person-url}}", jsonObj.personUrl));
    // etc
    $("#target-container").append($clone);
}
Zack
  • 385
  • 2
  • 3
  • 21