Search code examples
javascriptbackbone.js

How to build a table with vertical and horizontal data related to each other in Backbone


I'm building a sports chart of which country has participated in a certain sport based on years.

I have a list of countries (6 countries). And I have a list of years (1970 - 2016).

I have a table, years at the top (horizontally) and countries on the left (vertically). Under each cell of years, I have to put either 'Yes' or 'No' (whether the country participated or not) This is how I structured my data:

countries: [
   {name: 'UK', years: [ 1999, 2003 ] },
   {name: 'US', years: [ 1992, 2005 ] },
]

Creating the list of names (on the left hand side) was easy but can't figure out how to create years at the top and then how to pin point them with countries?

Should I have years in a separate collection?


Solution

  • Assuming you have a Country model with 2 attributes, name and years (array).

    I'm going to answer as if you're using templates. If you're not, it's fine because the logic is the same.

    var Countries = Backbone.Collection.extend({
        model:Country,
        tpl:_.template($('#table-tpl').html()),
        render:function(){
            var tableHtml = this.tpl({countries:this.collection.toJSON()})
            this.$el.html(tableHtml)
            return this;
        }
    })
    

    HTML template

    <script type="text/template" id="table-tpl">
    <table>
        <thead>
            <tr>
            <th>Country</th>
                <% _.each(_.range(1970,2017),year=>{%>
                    <th><%= year %></th>
                <% }) %>
            </tr>
        </thead>
        <tbody>
            <% _.each(countries, country =>{%>
                <tr>
                    <td><%= country.name %></td>
                    <% _.each(_.range(1970,2017),year=>{%>
                        <th><%= _.indexOf(country.years, year, true) != -1 ? 'Yes':'No'  %></th>
                    <% }) %>
                </tr>
            <% }) %>
        </tbody>
    </table>
    </script>
    

    NOTE: the true in _.indexOf(country.years, year, true) means that the input array, country.years is sorted. This allows for faster searching.

    Example fiddle: https://jsfiddle.net/guanzo/nod6g3hy/