MithrilJS, create HTML table from 2D array of data
Tags: mithril, javascript
Published: 2023-10-17 16:44:13

_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](https://mithril.js.org/) 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. 

```js
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)
          })
        )})
      )
    ])
  }
}
```
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:
```js
oninit: function(vnode){
  this.data = vnode.attrs.data
},
```
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:
```js
  oninit: function(vnode){
    this.data = vnode.attrs.data,
    this.title = vnode.attrs.title
  },
```
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...
```js
oninit: function(vnode){
  this.data = vnode.attrs.data,
  this.title = vnode.attrs.title,
  this.titleClass = vnode.attrs.titleClass
},
```
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:
```js
oninit: function(vnode){
  self = vnode.attrs
},
```
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: 
```js 
self.title
``` 
instead of (common) way:
```js 
this.title
```

####--> 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:
```js 
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"]
];
```

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:
```js 
m(table, {data: data1, title: "Numbers", titleClass: "text-red text-center text-bold"})
```

```js 
m(table, {data: data2})
```

Live example is at this flems.io [link](https://flems.io/#0=N4IgtglgJlA2CmIBcA2AjAOgKwCYA0IAxgPYB2AzsQskVbAIYAO58UIBAZhAucgNqhS9MIiQgMACwAuYWO1qkp8RTQA8AI2JQAngD4AOqUOqA9Jp275LBISkQyvMTiQAGEAF88g4aPEArXgISRWUpGgA3egAnAAIoeil6NBiAXhi+Qxj0gFp8GOy0PBiXIsKYnABdPEz0gGYi+pjG5qqavmysIuzGkpiAFjyATkGKwwqAbkNDSNj4xJxU9Lb9EAApYgkjdhiVgFloqO0VopWABXglKJXW0iy+HBcXRoeXAHYil7Qbu5XyKQBXKChY47EAAdyiEEuIJWYOIUQA1vAriBRqQJlNSDMYol1AhFsAamQIKQoUgYhx-qRbPZSAAKcKkLTwACUhNuWRiJgAVDUslIJBByBg5vRFozmRgElIosLRdUOfzBcK7FJ8WkJUCpVIZSqoQgFZyccqMKqEABhBjkcjipla6Wy036+CW+jWvkxbkmD3WDi2yUO8g1Tw1cIQeBg8mU6l2MgMu2s9lGqIXf5RW5gOkrKAQcIgjKKzmZla4hAwwtG31OtXwD1GgD8MWLIBl5aN7aLWZbUBBwBIsHIjHopHJVdFfBcFQwCFIAHMBUVCFbyKP4LAONWLcvPDEq2bWXX2yydhXOeTSP9YLBDR3d2uN6KMGAmHTozS4zK2Yfk6n002u622wyk+L5vrG9JSFAX6nh2KYAn+zaQb2S5uiuoJKAAHlI2SEKEyIrDukEst+nLuMRMExCyZGHuRRoVLRMTuIYTFGFi0QxEOs7wASobhpGFJUu+9LQT+8EZl2OZ5tsBYds2Eh9DCLb0Hi3FlGCUISDizorCyN5GpmpbwEUwCiuSoplPu5IrAAcv8YDqMiQZAc6rrWlZLbwFh2QplAOKedhuEhLEmHYZosA9h4umHnJCnbCWyn4nk6kCsQ-xSFpNY6XpnaGcZplxAk9A4NRhb0ZMHIse45WGGAT6pYodJQMQhB2aEGDmNoRScay5VWGu8BCY4IB9FgqDZCNSA4IMHheCAQgiDQGCENa8jBEoKhiIZMRJjEmhRECUTkjgjAYbuVDQLtDCEAi5VZHtB3efQOb-GhLgYK8WApmAt0cU9OZzuSb04J98DfTU6j0Nds5RPVUA4VQ8LkgAxI85rmgAguj5UsYYC44r5O2QKQ2TqVAArkn0X0-fdyLkmgJ1nbAF3Q-Q2jU-CD1RE9EAvYD2BUzUQ4wCSs587UINgxyENQzDVJw-2iMxGCgpKNjmKmv5OF4bEO0hdk9BM7OI4xIFlxq6xGteT5201Arh0xD55uGJboVUATNQcGQ2FgvAECztI5JhVA2N9TY4FDTgfSTW47hVCATOkAijgCHNPg0JAAqQrAGABPIaZyGI0hSMwSAmCYVKMAis5LcQYAmBnEhZwAAjgGCtzg9caVnOeBC22iML45CEJCjBhLH7hAA).

Hope this is useful for you :-)