Here, we will learn about Add-Remove rows and columns dynamically using jQuery. Previously we have done it using AngularJS. If you want to refer that then you can refer it from has. We will also save the data in the database for the table.

We are going to use code first approach, if you have no idea about it then you can refer it from here.

All the stuff we will be doing is performed using jQuery. So you must have an idea about jQuery.

So let’s begin building our awesome project.

Firstly create the table and name it as DynaTable.

public class DynaTable
    {
        [Key]
        public int Id { get; set; }

        public string Created_By { get; set; }

        public Nullable<System.DateTime> Created_Date { get; set; }

        public string Soil_Rows { get; set; }

        public string Soil_Columns { get; set; }

        public string Soil_Header { get; set; }

        public string Soil_Footer { get; set; }
    }

Navigate to Scripts -> Add DynamicTable.js file in it.

$('#DynamicTableCreation').empty();
var tempS = '';
tempS += '<tr class="lightgreen">';
tempS += '    <td></td>';
tempS += '    <td style="width:10%;"><input type="text" class="form-control no-border" value="Invoice" /></td>';
tempS += '    <td style="width:20%;"><input type="text" class="form-control no-border" value="Name" /></td>';
tempS += '    <td style="width:10%;"><input type="text" class="form-control no-border" value="Rate / Ac" /></td>';
tempS += '    <td><input type="text" class="form-control no-border" value="Comments" /></td>';
tempS += '</tr><tr>';
tempS += '    <td><button type="button" class="btn btn-xs btn-default btn-remove btnSpacing"><i class="fa fa-times"></i></button><button type="button" class="btn btn-xs btn-default" onclick="appendRowNext_Drp(\'TblDynamic\', this)"><i class="fa fa-plus"></i></button></td>';
tempS += '    <td><input type="text" class="form-control no-border" value="Product" /></td>';
tempS += '    <td><input type="text" class="form-control no-border" value="Test" /></td>';
tempS += '    <td><input type="text" class="form-control no-border" value="Test" /></td>';
tempS += '    <td><input type="text" class="form-control no-border" value="Test" /></td>';
tempS += '</tr>';
var Dynamic = '';
Dynamic += '<h4>Dynamic Add-Remove Rows And Columns In jQuery</h4>';
Dynamic += '<div class="row"><textarea class="form-control bottom-border" id="tableHead" placeholder="Header Text"></textarea></div>';
Dynamic += '<div class="row">';
Dynamic += '    <div class="col-md-12">';
Dynamic += '        <div class="container" id="DivTblDYCNR">';
Dynamic += '            <div class="table-editable table-responsive">';
Dynamic += '                <div class="btn-group pull-right p-tb-10" style="margin-right:10px;margin-top:10px;margin-bottom:10px">';
Dynamic += '                    <button type="button" class="btn btn-xs btn-default" onclick="appendColumn_Drp(\'TblDynamic\')"><i class="glyphicon glyphicon-plus"></i></button>';
Dynamic += '                    <button type="button" class="btn btn-xs btn-default"> Column</button>';
Dynamic += '                    <button type="button" class="btn btn-xs btn-default" onclick="deleteColumn(\'TblDynamic\')"><i class="glyphicon glyphicon-minus"></i></button>';
Dynamic += '                </div>';
Dynamic += '            </div>';
Dynamic += '        </div>';
Dynamic += '    </div>';
Dynamic += '</div>';
Dynamic += '<div class="row">';
Dynamic += '    <div class="table-editable table-responsive">';
Dynamic += '        <table class="table table-bordered" id="TblDynamic"> ' + tempS + '</table>';
Dynamic += '    </div>';
Dynamic += '</div>';
Dynamic += '<div class="row">';
Dynamic += '    <textarea class="form-control bottom-border" id="tableFooter" placeholder="Footer Text"></textarea>';
Dynamic += '</div>';
$('#DynamicTableCreation').prepend(Dynamic);

Again navigate to Scripts -> Add DynamicOperations.js file in it.

function appendRowNext_Drp(id, cellId) {
    var cell = cellId.parentNode.parentNode;
    var tbl = document.getElementById(id), row = tbl.insertRow(cell.rowIndex + 1), i;
    if (id == 'TblDynamic') {
        for (i = 0; i < tbl.rows[0].cells.length; i++) {
            if (i == 0) {
                CreateAddNextRowIcon(row.insertCell(i), id);
            }
            else {
                CreateTextBox(row.insertCell(i), i, 'form-control bottom-border', id);
            }
        }
    }
}
function CreateAddNextRowIcon(cell, id) {
    var button = document.createElement('button');
    button.setAttribute('type', 'button');
    button.setAttribute('class', 'btn btn-xs btn-default btn-remove btnSpacing');
    var i = document.createElement('i');
    i.setAttribute('class', 'fa fa-times');
    button.appendChild(i);
    cell.appendChild(button);

    var button = document.createElement('button');
    button.setAttribute('type', 'button');
    button.setAttribute('class', 'btn btn-xs btn-default');
    button.setAttribute('onclick', 'appendRowNext_Drp(\'' + id + '\', this)');
    var i = document.createElement('i');
    i.setAttribute('class', 'fa fa-plus');
    button.appendChild(i);
    cell.appendChild(button);
}
function CreateTextBox(cell) {
    var input = document.createElement('input');
    input.setAttribute('type', 'text');
    input.setAttribute('class', 'form-control no-border');
    cell.appendChild(input);
}
$(document).on("click", ".btn-remove", function () {
    debugger
    var row = $(this).parents('tr');
    var tablerow = $(this).parents('tr').parents('tbody');
    var cnt = tablerow.find('tr').length;
    if (cnt > 2)
        row.detach();
});
function appendColumn_Drp(id) {
    var tbl = document.getElementById(id), i;
    if (id == 'TblDynamic') {
        for (i = 0; i < tbl.rows.length; i++) {
            createCell(tbl.rows[i].insertCell(tbl.rows[i].cells.length), i, 'form-control no-border');
        }
    }
}
function createCell(cell, text, style) {
    var input = document.createElement('input');
    input.setAttribute('type', 'text');
    input.setAttribute('class', style);
    cell.appendChild(input);
}
function deleteColumn(id) {
    var tbl = document.getElementById(id), lastCol = tbl.rows[0].cells.length - 1, i;
    if (lastCol > 2) {
        for (i = 0; i < tbl.rows.length; i++) {
            tbl.rows[i].deleteCell(lastCol);
        }
    }
}
$(document).on("click", ".btn-remove-col", function () {
    var ndx = $(this).parent().index() + 1;
    $("td", event.delegateTarget).remove(":nth-child(" + ndx + ")");
});

Navigate to View -> Shared -> _Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Dynamic Rows and Columns</title>
    <style>
        .btn-remove {
            margin-top: 5px;
            margin-right: 0px;
        }
        .no-border {
            border: none !important;
            -webkit-box-shadow: none !important;
            box-shadow: none !important;
            -webkit-transition: none !important;
            padding: 0px !important;
            background-color: transparent;
            color: #000000;
        }
        #TblDynamic td, th {
            vertical-align: top !important;
        }
        .table-bordered {
            border: 5px solid #ddd !important;
        }
        .table-bordered > tbody > tr > td {
            border: 5px solid #ddd !important;
        }
        .btnSpacing {
            margin-top: 0px;
            margin-right: 10px
        }
    </style>
</head>
<body>

    <div class="container body-content">
        @RenderBody()

    </div>

</body>
</html>

Open View -> Home -> Index.cshtml and add following code in it.

@{
    ViewBag.Title = "Home Page";
}
<div id="DynamicTableCreation"></div>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="~/Scripts/DynamicOperations.js"></script>
<script src="~/Scripts/DynamicTable.js"></script>


<div id="DynamicTableCreation"></div>


<div class="col-xs-12" style="margin-top: 20px;">
    <button id="SaveTable" type="button" class="btn btn-primary pull-right" style="display: block;">Submit</button>
</div>

<script>
    $(document).on('click', '#SaveTable', function () {
        var status = true;
        if (status == true) {
            if ($('#DynamicTableCreation').html() != "") {
                var TempData = [];
                var Th = {};

                var $STrows = $('#TblDynamic').find('tr');
                var Soil_Rows = '', Soil_Columns = '';
                $STrows.each(function (index) {
                    var $td = $(this).find('td');
                    if (index == 0) {
                        $td.each(function (i) {
                            if (i > 0) {
                                Soil_Columns += $(this).find('.form-control').val() + '#sep#';
                            }
                        });
                    }
                    else {
                        $td.each(function (i) {
                            if (i > 0) {
                                Soil_Rows += $(this).find('.form-control').val() + '#sep#';
                            }
                        });
                    }
                    Soil_Rows += '#row#';
                });

                Th["Soil_Header"] = $('#tableHead').val();
                Th["Soil_Footer"] = $('#tableFooter').val();
                Th["Soil_Columns"] = Soil_Columns;
                Th["Soil_Rows"] = Soil_Rows;
                TempData.push(Th);
                var datas = JSON.stringify(TempData[0]);
                $.ajax({
                    url: '/Home/Index',
                    type: "POST",
                    data: { 'JsonData': datas },
                    success: function (result) {
                        alert("Data Added Successfully");
                    },
                    error: function (error) {

                    }
                });
            }
            else {

            }
        }
    });
</script>

Finally the login for adding data of table in the database.

Open the controller and add the code given below and you are done with it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DynamicRowsAndColumns.Models;
using Newtonsoft.Json;

namespace DynamicRowsAndColumns.Controllers
{
    public class HomeController : Controller
    {
        private readonly Context _context;
        public HomeController()
        {
            _context = new Context();
        }
        public ActionResult Index()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Index(string JsonData)
        {
            try
            {
                DynaTable TempData = (DynaTable)Deserialize(JsonData, typeof(DynaTable));
                DynaTable dt = new DynaTable()
                {
                    Created_By = "Test",
                    Created_Date = DateTime.Now,
                    Soil_Rows = TempData.Soil_Rows,
                    Soil_Columns = TempData.Soil_Columns,
                    Soil_Footer = TempData.Soil_Footer,
                    Soil_Header = TempData.Soil_Header
                };
                _context.DynaTables.Add(dt);
                _context.SaveChanges();
            }
            catch (Exception ex)
            {
                
            }
            return View();
        }
        public static object Deserialize(string json, Type type)
        {
            return JsonConvert.DeserializeObject(json, type);
        }
    }
}

Output:

output

You can download the source code from here