How to create a Dynamic Table with JavaScript

Facebook logoTwitter logoLinkedin logo
A snapshoot of an interacive table Editor tool

Today I got a very exciting project for you to learn about web development and building Interactive UI with HTML CSS JavaScript, We are going to build an Interactive dynamic Table with HTML CSS JavaScript, We are going to be able to Create and Delete Rows and Columns Alos we going to be able to edit the cells, All this will be wrapped around a simple and easy to use UI.

What is a table

A table is an arrangement of information or data, typically in rows and columns, or possibly in a more complex structure. Tables are widely used in communication, research, and data analysis.
Wikipedia

What we are going to learn

We are going to learn How to interact With the DOM (Document Object Module) create and delete Elements using JavaScrip, And most important we are going to learn How to build useful tools with the skills we have.

Let's Start Building an interactive Table editor

We are going to use HTML/CSS and JavaScript to build this Dynamic Table editor,
You will find the source code on my Github repository here, feel free to use edit, or sell it.

.Step 1 Project Setup

First will setup the project folder and file structure it's going to be fairly simple since the project is not that big.

Create a folder at your computre and it's going to have 3 main files index.html style.css app.js as shown down here in the shnapshoot

Project Folder structure

.Step 2 HTML Mockup

The HTML mockup consists of a page title and table also there are a few buttons that will allow us to control the table later when we add JavaScript Code

For Icons I'm using the Boxicons library it has great looking Icon free to use and its easy to implement in your projects, also it has Good documentation

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Table editor</title>
        <link
            href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css"
            rel="stylesheet"
        />
        <link rel="stylesheet" href="style.css" />
        <script defer src="/app.js"></script>
    </head>
    <body>
        <h1 class="title">Interactive table editor</h1>
        <div class="container">
            <div class="table-wrapper">
                <!-- when this button is clicked it will add a column to the table -->
                <button class="circle-button add-column" title="Add Column">
                    +
                </button>
                <!-- And this button will add a row to the table -->
                <button class="circle-button add-row" title="Add Row">+</button>
                <!-- This button will appear next to a row when it's focused -->
                <!-- When it's clicked it will delete the entire row -->
                <button
                    id="delete-row"
                    class="delete-btn point-right"
                    title="Delete this row"
                >
                    <i class="bx bx-trash"></i>
                </button>
                <!-- This button will appear on top of each column when it's focused -->
                <!-- Also when it's clicked will delete the row below it -->
                <button
                    id="delete-column"
                    class="delete-btn point-bottom"
                    title="Delete this Column"
                >
                    <i class="bx bx-trash"></i>
                </button>
                <!-- This is the main table will use it as a demo -->
                <table class="table">
                    <thead>
                        <tr>
                            <th>#</th>
                            <th>Name</th>
                            <th>Position</th>
                            <th>Location</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>1</td>
                            <td>Bob Dylan</td>
                            <td>Musician</td>
                            <td>California, USA</td>
                        </tr>
                        <tr>
                            <td>2</td>
                            <td>Eric Clapton</td>
                            <td>Musician</td>
                            <td>Ohio, USA</td>
                        </tr>
                        <tr>
                            <td>3</td>
                            <td>Daniel Kahneman</td>
                            <td>Psychologist</td>
                            <td>California, USA</td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </body>
</html>
Copy

.Step 3 CSS styling

Adding CSS styles will be very easy at top of the style.css file will add some global styles and rests so the UI will be consistent in all the browsers, as you can see we are using CSS variables if you are not familiar with it just check this blog post by freecodecamp it will help you learn more about them

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    --accent: #1977e2;
}

html {
    font-size: 15px;
}

body {
    font-size: 1rem;
    line-height: 1.5;
    font-weight: 400;
    background-color: white;
    letter-spacing: 0.02em;
    font-family: Inter, sans-serif;
}
Copy

Next we will add styles on the page title and linear gradient as text color it will look cool as show here

If you like to go indepth in css I highly recomend the blog by Manuel Matuzović you will learn a lot for it

.title {
    text-align: center;
    margin-top: 3rem;
    margin-bottom: 5rem;
    font-size: 40px;
    text-transform: capitalize;
    background: linear-gradient(45deg, var(--accent), #1bffff);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
Copy

And this is hwo it looks like very cool right

css linear gradient text color effect

After that will add styles to thebuttons and as well as the container of the page and table wrapper

/* Page container */
.container {
    padding: 0 2rem;
    max-width: 1100px;
    margin: 0 auto;
}

/* Buttons styles */
button {
    border: 0;
    outline: 0;
    cursor: pointer;
    line-height: 1;
}

button:hover {
    opacity: 0.9;
}

.delete-btn {
    display: none;
    position: absolute;
    background-color: #ffd8d8;
    font-size: 17px;
    width: 26px;
    height: 26px;
    color: #e61919;
    border-radius: 4px;
    left: -31px;
    top: 0;
}

.delete-btn.active {
    display: initial;
}

.delete-btn.point-right::after,
.delete-btn.point-bottom::after {
    content: "";
    display: inline-block;
    position: absolute;
    border: 4px solid transparent;
}

.delete-btn.point-right::after {
    right: -8px;
    top: 9px;
    border-left-color: #ffd8d8;
}

.delete-btn.point-bottom::after {
    bottom: -8px;
    left: 9px;
    border-top-color: #ffd8d8;
}

.circle-button {
    background-color: var(--accent);
    color: white;
    width: 24px;
    height: 24px;
    font-size: 18px;
    display: inline-flex;
    justify-content: center;
    align-items: center;
    border-radius: 50%;
}

.table-wrapper {
    position: relative;
    max-width: 100%;
}

.add-column {
    position: absolute;
    right: -24px;
    top: calc(20px - 12px);
    border-radius: 0 50% 50% 0;
}
.add-row {
    position: absolute;
    bottom: -24px;
    left: calc(50% - 12px);
    border-radius: 0 0 50% 50%;
}
Copy

Now onlay the table is left wethout styling it going to be very easy

The border-collapse property sets whether table borders should collapse into a single border or be separated as in standard HTML.
w3schools
border-collapse property  defrence between  collapse and separate
.table {
    width: 100%;
    /* This one the most important property when it comes */
    /* to Adding borders to the table */
    border-collapse: collapse;
    text-align: center;
    vertical-align: middle;
}

.table th,
.table td {
    border: 1px solid #ddd;
    padding: 8px 14px;
}

/* When the cell is focused will add an outline to highlighted */
.table th:focus,
.table td:focus {
    outline: 1.5px solid #6998ce;
    outline-offset: -1px;
}
Copy

Step 4 and Most important Adding javaScript functionality

First will create a simple function that will help us select elements from the DOM easily, basically, we are just going to wrap it around the document.querySelector and document.querySelectorAll based on the given parameter if we call it like this $("div") it going to return a single div element from the DOM, If we call with parameters like this $("ul li", true) it will return an array of elements based on the given selector

If you are not familiar with the querySelector method just check out this article by MDN It will help learn more about its very important method when it comes to interacting with DOM

function $(selector, selectAll = false) {
    if (selectAll) {
        return document.querySelectorAll(selector);
    }
    return document.querySelector(selector);
};
Copy

Have you ever wandered how you can add you own custom method on all HTML Elements will today we are going to learn how

If you want to add custom method that you can You just have to add your method to the HTMLElement class

We are going to access the HTMLElement prototype and will add a new method will call it on basically on method will simplify how we add events

HTMLElement.prototype.on = function (event, callback) {
    this.addEventListener(event, callback);
};
Copy

Now let's see how we can use these helper functions and methods, Let's say we want to select a button from the DOM that has a class of btn and we want to add a click event when that button is clicked we will log to the console hello word message

// Select the button from the DOM
let btn = $('.btn');
// Add click event on the button
btn.on('click', (event) => {
    console.log("Hello world!")
});
Copy

Now that out of the way let strat working building the Dynamic interactive table editor

Will add these variables on the top of the app.js file so that when we focus on a row or column we will assign it to the proper variable, by default it is set to null

And they should be declared by using the let keyword, not const because any variable declared by let you can overwrite its value but you can't with const you can learn more about the difference between let and const here

let selectedRow = null;
let selectedColumn = null;
Copy

After that we need to grab all the buttons and Elements we need from the DOM

First will get all cells in the page which means all <th> and <td> tags inside of the table

const cells = $(".table th, .table td", true);
Copy

Second will grab all the buttons

const addColumnBtn = $(".add-column");
const addRowBtn = $(".add-row");
const deleteRowBtn = $("#delete-row");
const deleteColumnBtn = $("#delete-column");
Copy

Now we are going to make all cells in the table editable by setting the contentEditable attribute to "true" if the contnetEdibale attribute is set to "true" it allows us to edit the text inside element

And register events on the cells based on its tag

cells.forEach((cell) => {
    // make the cells editable
    cell.contentEditable = "true";
    registerCellEvents(cell, cell.tagName.toLowerCase());
});
Copy

And this is what the registerCellEvents the function does, it adds the focus event on the cell and calls the handleCellFocus function if the tag is td if the tag is th It will call the handleCellHeadFocus function

function registerCellEvents(cell, cellType) {
    if (cellType === "td") {
        cell.on("focus", handleCellFocus);
    }
    if (cellType === "th") {
        cell.on("focus", handleCellHeadFocus);
    }
}
Copy

Now let see what these function does

The handleCellFocus function when it is called will get the row of the table which is the parent Element of the td we will call it row as shown down here, New will set the selectedRow variable to the currently focused row, then will make the delete row button active by adding the active class it will make it visible, and then we set its position relative to the selected row by getting the offsetTop property on the row

function handleCellFocus(e) {
    let row = e.target.parentElement;
    selectedRow = row;
    deleteRowBtn.classList.add("active");
    deleteRowBtn.style.top = row.offsetTop + 6 + "px";
}
Copy

Now will put the delete column button on top of the focused head cell, When the cells are focused will call the function handleCellHeadFocus this function will set selectedColumn to the currently focused cell in the head of the table and then it will active the delete column button, Next It will get the left and the top position values from the cell in order to put the button on top of the selected column

function handleCellHeadFocus(e) {
    let column = e.currentTarget;
    selectedColumn = column;
    deleteColumnBtn.classList.add("active");
    let y = column.offsetTop - deleteColumnBtn.clientHeight - 6 + "px";
    let x =
        column.offsetLeft +
        column.clientWidth / 2 -
        deleteColumnBtn.clientWidth / 2 +
        "px";
    deleteColumnBtn.style.top = y;
    deleteColumnBtn.style.left = x;
}
Copy

And this leads us to the next task, When the the delete buttons are clicked will handle theme

Will start with the delete row button, First will register the click event when its clicked will call the deleteRow function to handle the deletion or the currently selected row, which what assigned to the selectedRow variable before when the row was focused

deleteRowBtn.on("click", deleteRow);
Copy

Now let us see the deleteRow function what it does when it's called

So basically, it checks if there is a selected row, and if there is it will remove it from the DOM by calling the remove() method on the selectedRow element and then it will remove the active class from the delete row button so it won't be visible

function deleteRow(e) {
    if (selectedRow) {
        selectedRow.remove();
        deleteRowBtn.classList.remove("active");
    }
}
Copy

Now that's Done let see how can we delete a coulmn from the dynamic table editor

It checks if there is a selected column, and then it removes the active class from the delete column button, After that get the cell index It will help us determine what cells in the dynamic table rows should be deleted in order to delete the entire column, then It removes the cell in the head which is called the selectedColumn after that, it loops over all the rows in the dynamic table and for each row, it gets its children and then deletes the child with the same index as the cell in the head

function deleteColumn(e) {
    if (!selectedColumn) return;
    deleteColumnBtn.classList.remove("active");
    let cellIndex = selectedColumn.cellIndex;
    selectedColumn.remove();
    $(".table tbody tr", true).forEach((row) => {
        row.children[cellIndex].remove();
    });
}
Copy

Now will handle adding rows and columns as you can see hear

a snapshoop of a table editor

Before we start adding rows and columns we need a function that will help us create new cells

The createCell function takes a parameter which is the type of the cell and the type either it's going to be td or th then we make it editable by setting the attribute contentEditable to true after that will register the cell events as I explained before and return the cell Element

function createCell(type) {
    let cell_el = document.createElement(type);
    cell_el.contentEditable = "true";
    registerCellEvents(cell_el, type);
    return cell_el;
}
Copy

Let's start with adding new column, First will register a click event on the add column button

addColumnBtn.on("click", addColumn);
Copy

The add column button will call addColumn function it will handle adding new column to the dynamic table editor

If you arn't femailer with appendChild method checkout this article By javascripttutorial

function addColumn() {
    // Add a cell on the table head
    $(".table thead tr").appendChild(createCell("th"));
    // And add a cell on each row
    $(".table tbody tr", true).forEach((row) => {
        row.appendChild(createCell("td"));
    });
}
Copy

And this is How we are going to add new row to the table as you can see it is very easy

addRowBtn.on("click", addRow);
Copy

It creates a new row and then it loops over the cells in the table head and it adds a new cell to the new row after that will add the new row to the table body.

function addRow() {
    const row = document.createElement("tr");
    $(".table thead tr th", true).forEach((_) => {
        row.append(createCell("td"));
    });
    $(".table tbody").appendChild(row);
}
Copy

Conclusion

I hope you learn some valuable today This post was meant to help you learn how to interact with the DOM and level up your skills with JavaScript and also open your eyes to the possibilities of what you can build with JavaScript