DEV Community

Pavel Kříž
Pavel Kříž

Posted on

MithrilJS, create HTML table from 2D array of data

This is my 8th write up on dev.to site. I will show you Mithril component creating HTML table populated with data as two dimensional array.

Mithril JS

Mithril JS is an amazing JS framework, small and very effective. It can be used to program web/mobile apps, Single Page Applications (SPA). See the documentation for details.

Mithril component

There are many ways how to write component, one of them is JS object (a.k.a. POJO = Plain Old Javascript Object). Components can also receive and use data you put them.

Component table

We will write table component, so it creates HTML table and renders it into page in a browser.

var table = {
  oninit: function(vnode){
    /*
    this.data = vnode.attrs.data,
    this.title = vnode.attrs.title,
    this.titleClass = vnode.attrs.titleClass
    */
    self = vnode.attrs
  },
  view: function(vnode){
    return m("div", [
      m("table", 
        self.title
        ? m("tr", 
            m("td", {colspan: self.data[0].length, class: self.titleClass}, self.title)
          ) 
        : null,
        self.data.map(function(tr){
          return m("tr", tr.map(function(td){
            return m("td", {class: "text-center"}, td)
          })
        )})
      )
    ])
  }
}
Enter fullscreen mode Exit fullscreen mode

Let me explain my code. Table component consists of two functions - oninit(vnode) and view(vnode). Component (when used/called) receives one or more arguments (parameters) and both functions have access to them via vnode object.

---> oninit(vnode) function <---

Pay attentions to first one - oninit(vnode) - function. There are three commented lines of code; it is common way how to use parameters. Say, our component table needs data to create populated table's cells (html td tag). So, you write something like this:

oninit: function(vnode){
  this.data = vnode.attrs.data
},
Enter fullscreen mode Exit fullscreen mode

Everything looks good and works well, you are satisfied. Then you think about another parameter title. It would be great to have table with caption/title. Therefore you extend oninit(vnode) function and add second parameter:

  oninit: function(vnode){
    this.data = vnode.attrs.data,
    this.title = vnode.attrs.title
  },
Enter fullscreen mode Exit fullscreen mode

Looks good, table is pretty and useful. Is there any improvement? Yeah, what about class for title to customise it? And number of parameters grows...

oninit: function(vnode){
  this.data = vnode.attrs.data,
  this.title = vnode.attrs.title,
  this.titleClass = vnode.attrs.titleClass
},
Enter fullscreen mode Exit fullscreen mode

This (common) way means to add another line of code to specify another parameter. But there is even better way: one object, and that is one line of code below three commented lines:

oninit: function(vnode){
  self = vnode.attrs
},
Enter fullscreen mode Exit fullscreen mode

This is a little trick. You assign all parameters as one object to another object named self.
You can simply use any of parameters this way:

self.title
Enter fullscreen mode Exit fullscreen mode

instead of (common) way:

this.title
Enter fullscreen mode Exit fullscreen mode

--> view(vnode) function <---

This is a place where all magic happens :-) At the begining div tag is created (useful for horizontal shift when table is too wide), then table tag and optionally one row with one cell with title of table.
Data are iterated by map function, first it creates rows - tr tags - dependeded of y-dimension of data. Inside rows is another iteration by map function walking each piece of data in x-dimension.

Example of two data arrays we use for our table component:

var data1 = [
  [-2, -1, 0, 1, 2],
  [3, 3, 3, 3, 3],
  [-5, -3, 0, 42, 99]
];

var data2 = [
  ["John", "Marry", "Peter"],
  [2003, 2007, 2001],
  ["student", "writer", "worker"]
];
Enter fullscreen mode Exit fullscreen mode

Our table component simply gets data and creates corresponding rows and cols derived from data array.

use of table component

With the use of data1 and data2 arrays we use table component like this:

m(table, {data: data1, title: "Numbers", titleClass: "text-red text-center text-bold"})
Enter fullscreen mode Exit fullscreen mode
m(table, {data: data2})
Enter fullscreen mode Exit fullscreen mode

Live example is at this flems.io link.

Hope this is useful for you :-)

Top comments (1)

Collapse
 
artydev profile image
artydev

Thank you :-)