Sudheesh Singanamalla
Sudheesh Singanamalla

Reputation: 2297

Use JsRender to create a row/column layout from simple array data

I am using jsrender to write a bootstrap based HTML template and render the HTML content using javascript. My data is as follows

var data = [
    {
        'img': 'img/books/kiterunner.jpg',
        'title': 'The Kite Runner',
        'authors': 'Khaled Hosseini'
    },
    {
        'img': 'img/books/tokillamockingbird.jpg',
        'title': 'To Kill A Mocking Bird',
        'authors': 'Harper Lee'
    },
    {
        'img': 'img/books/hungergames.jpg',
        'title': 'The Hunger Games',
        'authors': 'Suzanne Collins'
    }
    .....
]

And the corresponding HTML I want to generate is as follows

<div class="row-fluid" id="result">
    <script id="template" type="text/x-js-render">
        <div class="col-md-3 col-sm-6">
            <div class="image-tile outer-title text-center">
                <img alt="{{:title}}" src="{{:img}}" style="max-height:350px;">
                <div class="title mb16">
                    <h5 class="uppercase mb0">{{:title}}</h5>
                        <span>{{:authors}}</span>
                </div>
            </div>
       </div>
   </script>
</div>

Currently each object in data gets displayed individually but sometimes, the images are larger in size and disrupt the way the row looks. So I want to repeat the div.row-fluid creation with the content after every 4 objects from data. I currently do the following to register the template and render the data into the required HTML. I can't seem to figure out how to use {{for}} without changing the values in data.

var template = $.templates("#template");
var htmlOutput = template.render(data);
$("#result").html(htmlOutput);

Thank you.

Edit: I have managed to do this by doing explicit HTML string concatenation and then rendering them while using index%4 in the if statements to decide on whether the div.row-fluid needs to be created. However, I would really like a more elegant solution. Adding jquery tag for wider visibility.

Upvotes: 0

Views: 682

Answers (1)

BorisMoore
BorisMoore

Reputation: 8524

You could use a custom {{range}} tag - see this sample.

Here is an example which renders into a table with <td>s grouped by four - for a four column layout:

<script id="myTmpl" type="text/x-jsrender">
  <table>
    {{for rows ~last=rows.length-1}}
      {{if #index%4===0 ~ind=#index}}
        <tr>
        {{range ~root.rows start=~ind end=~ind+3 max=~last}}
          <td>{{:title}}</td>
        {{/range}}
        </tr>
      {{/if}}
    {{/for}}
  </table>
</script>

using this version of a custom {{range}} tag:

$.views.tags("range", function(array) {
  var ret = "",
    start = this.tagCtx.props.start,
    end = this.tagCtx.props.end,
    max = this.tagCtx.props.max;

  end = end > max ? max : end;

  for (var i = start; i <= end; i++) {
    // Render tag content, for this data item
    ret += this.tagCtx.render(array[i]);
  }
  return ret;
});

var data = {rows: [
    {
        'title': ...
    },
    ...
  ]};

  ...

Upvotes: 1

Related Questions