Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
November 19, 2022 09:40 am GMT

Let's make a table component with JavaScript

In this tutorial, we'll make a table component with JavaScript. We'll make it can be populated with any data and add more features to it in the following series.

This is how a table is structured.
table demo screenshot from MDN

Let's write the overall structure.

// Create a `table` element and add `thead` and `tbody` to it.function createTable() {  const table = document.createElement('table')  const thead = createTableHead()  const tbody = createTableBody()  table.appendChild(thead)  table.appendChild(tbody)  return table}// create a thead elementfunction createTableHead() {  const thead = document.createElement('thead')  const tr = document.createElement('tr')  // add th of each column to tr  thead.appendChild(tr)  return thead}// create a tbody elementfunction createTableBody() {  const tbody = document.createElement('tbody')  // add tr of each row of data to tbody  return tbody}

Grab the dummy data from https://jsonplaceholder.typicode.com/users and store it in a variable.

const users = [   //...]

Define the default columns we want to display. we'll make the columns can be toggled on and off in later series.

const nameOfDefaultColumns = [  'id',  'name',  'username',  'email',  'phone',  'website',]

Add a parameter columns to createTableHead so it can make each th element according to columns.

function createTableHead(columns) {  const thead = document.createElement('thead')  const tr = document.createElement('tr')  // create th element for each column  columns.forEach(name => {    const th = document.createElement('th')    th.textContent = name    tr.appendChild(th)  });  thead.appendChild(tr)  return thead}

Add two parameter columns and dataList to createTableBody so it can make tr for each row of dataList and columns of each row.

function createTableBody(columns, dataList) {  const tbody = document.createElement('tbody')  // create rows for each item of dataList  dataList.forEach(eachDataObject => {    const tr = document.createElement('tr')    // create cells of each column for the row    columns.forEach((columnName) => {      const td = document.createElement('td')      // display the data of that column      td.textContent = eachDataObject[columnName]      tr.appendChild(td)    })    tbody.appendChild(tr)  });  return tbody}

Note that we use columns.forEach() to create column headers in createTableHead and create each column data of each row in createTableBody. This guarantees that the data of each column would match.

This is the code at this point.

const user = [ /* https://jsonplaceholder.typicode.com/users */ ]const nameOfDefaultColumns = [  'id',  'name',  'username',  'email',  'phone',  'website',]const table = createTable(nameOfDefaultColumns, users)document.body.appendChild(table)function createTable(columns, dataList) {  const table = document.createElement('table')  const thead = createTableHead(columns)  const tbody = createTableBody(columns, dataList)  table.appendChild(thead)  table.appendChild(tbody)  return table}function createTableHead(columns) {  const thead = document.createElement('thead')  const tr = document.createElement('tr')  columns.forEach(columnName => {    const th = document.createElement('th')    th.textContent = columnName    tr.appendChild(th)  });  thead.appendChild(tr)  return thead}function createTableBody(columns, dataList) {  const tbody = document.createElement('tbody')  dataList.forEach(eachDataObject => {    const tr = document.createElement('tr')    columns.forEach((columnName) => {      const td = document.createElement('td')      td.textContent = eachDataObject[columnName]      tr.appendChild(td)    })    tbody.appendChild(tr)  });  return tbody}

Our result.
the result at this point

We can easily change the columns we want to display.

const nameOfDefaultColumns = [  'id',  'name',  'username',  'email',  'phone',  'website',  'company' // add this]

The column appears! But the data is definitely not correct.
company data display [object object]

Because the data was converted to string before assigning to td.textContent, the toString() was called implicitly. When we call toString() on an object, it will return '[object Object]', This is also the reason why sometimes we try to console.log an object but we see '[object Object]', because it is implicitly converted to a string.

// a numberconst id = 1id.toString()// '1'// an objectconst obj = {}obj.toString()// '[object Object]'

This means we need to process the data before assigning to td.textContent. This also means that if we want to display something more complex, we can't use td.textContent because it will only display string.

We need a way to process the data inside createTableBody. But we can't directly process the data because the data from dataList is dynamic. So how do we process the data inside createTableBody but in the meantime control the actual process from outside? It is like how we pass data to createTableBody. This time we want to pass a formatter.

function createTableBody(columns, dataList, columnFormatter) {  const tbody = document.createElement('tbody')  dataList.forEach(eachDataObject => {    const tr = document.createElement('tr')    columns.forEach((columnName) => {      const td = document.createElement('td')      const columnValue = eachDataObject[columnName]      // if we have a custom formatter for this column      // we want to use it      if (columnFormatter && columnFormatter[columnName]) {        const formatterOfColumn = columnFormatter[columnName]        if (formatterOfColumn) {          const formatted = formatterOfColumn(columnValue)          // append accept both string and node          td.append(formatted)        }      }      else {        // otherwise we simply display the "string version" value        td.textContent = columnValue      }      tr.appendChild(td)    })    tbody.appendChild(tr)  });  return tbody}

We call createTableBody from createTable, so we also need to add the columnFormatter parameter to createTable in order to pass it.

// add columnFormatter parameterfunction createTable(columns, dataList, columnFormatter) {  const table = document.createElement('table')  const thead = createTableHead(columns)  // call createTableBody with columnFormatter  const tbody = createTableBody(columns, dataList, columnFormatter)  table.appendChild(thead)  table.appendChild(tbody)  return table}

Define column formatter. An object that each key is the column name and maps to a function that process the column value.

const columnFormatter = {  'company': (data) => {    const p = document.createElement('p')    const strong = document.createElement('strong')    strong.textContent = ` (${data.catchPhrase})`    p.append(data.name, strong)    return p  },  'address': (data) => {    const {      street,      suite,      city,      zipcode,    } = data    // I don't know how people format address in US.    // Sorry if this is incorrect    return `${street} ${suite} ${city} ${zipcode}`  }}const table = createTable(nameOfDefaultColumns, users, columnFormatter)document.body.appendChild(table)

Display all columns with processed values.
screenshot

This is great! We've already done what we need. It should be able to populate any data. There is one last thing I want to do before closing. Let's refactor the code a little bit.

Move the logic that makes table row from createTableBody to a new function createTableRow so the code can be more readable.

function createTableBody(columns, dataList, columnFormatter) {  const tbody = document.createElement('tbody')  dataList.forEach(eachDataObject => {    const tr = createTableRow(columns, eachDataObject, columnFormatter)    tbody.appendChild(tr)  });  return tbody}function createTableRow(columns, dataOfTheRow, columnFormatter) {  const tr = document.createElement('tr')  columns.forEach((columnName) => {    const td = document.createElement('td')    const columnValue = dataOfTheRow[columnName]    if (columnFormatter && columnFormatter[columnName]) {      const formatterOfColumn = columnFormatter[columnName]      if (formatterOfColumn) {        const formatted = formatterOfColumn(columnValue)        td.append(formatted)      }    }    else {      td.textContent = columnValue    }    tr.appendChild(td)  })  return tr}

Original Link: https://dev.to/gohomewho/lets-make-a-table-component-with-javascript-2i66

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To