Bootstrap Datatable CRUD using Codeigniter, MySQL, AJAX

Introduction

In this post we will see Bootstrap Datatable CRUD using Codeigniter, MySQL and AJAX. We have also seen similar implementation in our previous post on DataTable CRUD Example using Codeigniter, MySQL and AJAX, but here we will use Bootstrap Datatable to implement the similar functionalities, where we have the following features:

  • Loading data from MySQL database in HTML table
  • Pagination – each page shows 10 records
  • Searching
  • Filtering
  • Sorting
  • Creating new record
  • Updating the existing record
  • Deleting the existing record

In this example we will use Bootstrap 4 Datatable API to implement our example.

Prerequisites

PHP 7.3.5, Codeigniter 3.1.10, jQuery 3.4
MySQL 5.6, Apache HTTP server 2.4, AJAX

Go through the following sections to implement the CRUD(Create Read Update Delete) example.

Creating MySQL Table

First thing first! So let’s create a table called products in the MySQL server. We have few self explanatory columns in the table as shown below:

CREATE TABLE `products` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `price` double NOT NULL,
  `sale_price` double NOT NULL,
  `sales_count` int(10) unsigned NOT NULL,
  `sale_date` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Dumping Some Data

We will test our application once we are done with our coding. So you can create records and add to the table but to test the application quickly it is always good thing to dump some data into the database.

insert  into `products`(`id`,`name`,`price`,`sale_price`,`sales_count`,`sale_date`) values 
(1,'Desktop',5,10,10,'21-0-2019'),
(4,'Phone',15000,17505,251,'05-04-2018'),
(5,'Phone',18000,22080,178,'05-04-2018'),
(6,'Tablet',30500,34040,58,'05-04-2018'),
(7,'Adapter',2000,2500,68,'06-04-2018'),
(8,'TV',45871,55894,165,'07-04-2018'),
(9,'Laptop',67000,75000,2,'19-03-2019'),
(10,'Laptop',120000,150000,100,'19-03-2019'),
(11,'Tab',23000,300000,20,'18-03-2019'),
(12,'Tab',34000,45000,24,'17-03-2019'),
(14,'Mobile',23000,45000,24,'16-02-2019'),
(15,'Mobile',24000,50000,34,'12-02-2019'),
(16,'cc',111,11111,1,''),
(18,'xcxc',0,0,0,''),
(19,'wew',0,0,0,'');

Creating Project Directory

It’s assumed that you have setup Apache 2.4, PHP 7.3.5 and Codeigniter 3.1.10 in Windows system.

Now we will create a project root directory called codeIgniter-3.1.10-bootstrap-datatable under the Apache server’s htdocs folder.

Now move all the directories and files from CodeIgniter 3.1.10 framework into codeIgniter-3.1.10-bootstrap-datatable directory.

We may not mention the project root directory in subsequent sections and we will assume that we are talking with respect to the project’s root directory.

Database Configurations

Configure the database setup in application/config/database.php . If you have different configurations then you can change accordingly.

'username' => 'root',
'password' => '',
'database' => 'roytuts',

Autoload Configuration

We need some configurations, such as, auto-loading helpers to avoid loading every time we need to use.

Modify application/config/autoload.php file for auto-loading libraries and helper functions.

This one time auto-loading gives flexibility to uniformly use the helpers and libraries anywhere throughout the application without loading repeatedly.

$autoload['libraries'] = array('database');
$autoload['helper'] = array('url', 'file');

Codeigniter Model Class

We perform database operations to store, fetch or update data into database.

We want data to be fetched from database table – products and we will display on the Bootstrap Datatable. We will also perform Add, Update, and Delete operations.

Create a file BootStrapDatatable_Model.php under applications/models folder to create the required model class.

As usually the below model class extends CI_Model class. At the beginning of the class we first declare our table, products, using a variable. Next we have defined get_products() method, where we perform filter, sort, pagination before fetching the final data from the products table.

Notice how I have structure the final results to display using Bootstrap Datatable API.

Notice also how I have put the Edit and Delete buttons for each row to perform update and delete operations.

As we are performing CRUD operations, so our next methods are delete_product(), update_product() and add_product() to delete an existing product, to update an existing product and add a new product, respectively.

You will find one difference between this example and previous example.

In our previous example we had used SQL_CALC_FOUND_ROWS which is a query modifier and accompanying FOUND_ROWS() function but I did not use it here because SQL_CALC_FOUND_ROWS has been deprecated as of MySQL 8.0.17 and will be removed in a future MySQL version.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
	
/**
* Description of BootstrapDatatable_Model
*
* @author https://roytuts.com
*/
class BootstrapDatatable_Model extends CI_Model {
	
	private $products = 'products';
	function get_products() {		
		//columns
		$columns = array(
            'id',
            'name',
            'price',
            'sale_price',
            'sales_count',
            'sale_date');
		
		//index column
		$indexColumn = 'id';
		
		//total records
		$sqlCount = 'SELECT COUNT(' . $indexColumn . ') AS row_count FROM ' . $this->products;
		$totalRecords = $this->db->query($sqlCount)->row()->row_count;
		
		//pagination
		$limit = '';
		$displayStart = $this->input->get_post('start', true);
		$displayLength = $this->input->get_post('length', true);
		
		if (isset($displayStart) && $displayLength != '-1') {
            $limit = ' LIMIT ' . intval($displayStart) . ', ' . intval($displayLength);
        }
		
		$uri_string = $_SERVER['QUERY_STRING'];
        $uri_string = preg_replace("/%5B/", '[', $uri_string);
        $uri_string = preg_replace("/%5D/", ']', $uri_string);
        $get_param_array = explode('&', $uri_string);
        $arr = array();
        foreach ($get_param_array as $value) {
            $v = $value;
            $explode = explode('=', $v);
            $arr[$explode[0]] = $explode[1];
        }
		
		$index_of_columns = strpos($uri_string, 'columns', 1);
        $index_of_start = strpos($uri_string, 'start');
        $uri_columns = substr($uri_string, 7, ($index_of_start - $index_of_columns - 1));
        $columns_array = explode('&', $uri_columns);
        $arr_columns = array();
		
		foreach ($columns_array as $value) {
            $v = $value;
            $explode = explode('=', $v);
            if (count($explode) == 2) {
                $arr_columns[$explode[0]] = $explode[1];
            } else {
                $arr_columns[$explode[0]] = '';
            }
        }
		
		//sort order
		$order = ' ORDER BY ';
        $orderIndex = $arr['order[0][column]'];
        $orderDir = $arr['order[0][dir]'];
        $bSortable_ = $arr_columns['columns[' . $orderIndex . '][orderable]'];
        if ($bSortable_ == 'true') {
            $order .= $columns[$orderIndex] . ($orderDir === 'asc' ? ' asc' : ' desc');
        }
		
		//filter
		$where = '';
        $searchVal = $arr['search[value]'];
        if (isset($searchVal) && $searchVal != '') {
            $where = " WHERE (";
            for ($i = 0; $i < count($columns); $i++) {
                $where .= $columns[$i] . " LIKE '%" . $this->db->escape_like_str($searchVal) . "%' OR ";
            }
            $where = substr_replace($where, "", -3);
            $where .= ')';
        }
		
		//individual column filtering
        $searchReg = $arr['search[regex]'];
        for ($i = 0; $i < count($columns); $i++) {
            $searchable = $arr['columns[' . $i . '][searchable]'];
            if (isset($searchable) && $searchable == 'true' && $searchReg != 'false') {
                $search_val = $arr['columns[' . $i . '][search][value]'];
                if ($where == '') {
                    $where = ' WHERE ';
                } else {
                    $where .= ' AND ';
                }
                $where .= $columns[$i] . " LIKE '%" . $this->db->escape_like_str($search_val) . "%' ";
            }
        }
		
		//final records
		$sql = 'SELECT ' . str_replace(' , ', ' ', implode(', ', $columns)) . ' FROM ' . $this->products . $where . $order . $limit;
        $result = $this->db->query($sql);
		
		//total rows
		$sql = 'SELECT COUNT(*) AS count FROM ' . $this->products . $where . $order;
        $totalFilteredRows = $this->db->query($sql)->row()->count;
		
		//display structure
		$echo = $this->input->get_post('draw', true);
        $output = array(
            "draw" => intval($echo),
            "recordsTotal" => $totalRecords,
            "recordsFiltered" => $totalFilteredRows,
            "data" => array()
        );
		
		//put into 'data' array
		foreach ($result->result_array() as $cols) {
            $row = array();
            foreach ($columns as $col) {
                $row[] = $cols[$col];
            }
			array_push($row, '<button class=\'edit\'>Edit</button>  <button class=\'delete\' id='. $cols[$indexColumn] .'>Delete</button>');
            $output['data'][] = $row;
        }
		
		return $output;
	}
	
	function delete_product($id) {
		$sql = 'DELETE FROM ' . $this->products . ' WHERE id=' . $id;
		$this->db->query($sql);
		
		if ($this->db->affected_rows()) {
			return TRUE;
		}
		
		return FALSE;
	}
	
	function update_product($id, $name, $price, $sale_price, $sales_count, $sale_date) {
		$data = array(
					'name' => $name,
					'price' => $price,
					'sale_price' => $sale_price,
					'sales_count' => $sales_count,
					'sale_date' => $sale_date
				);
		
		$this->db->where('id', $id);
		$this->db->update($this->products, $data);
		
		if ($this->db->affected_rows()) {
			return TRUE;
		}
		
		return FALSE;
	}
	
	function add_product($name, $price, $sale_price, $sales_count, $sale_date) {
		$data = array(
					'name' => $name,
					'price' => $price,
					'sale_price' => $sale_price,
					'sales_count' => $sales_count,
					'sale_date' => $sale_date
				);
		
		$this->db->insert($this->products, $data);
		
		if ($this->db->affected_rows()) {
			return TRUE;
		}
		
		return FALSE;
	}
	
}
/* End of file Datatable_Model.php */
/* Location: ./application/models/BootstrapDatatable_Model.php */

Codeigniter Controller Class

Create a controller file BootstrapDatatable.php under application/controllers with the following source code.

The below controller class handles request and response for clients.

The below class extends Codeigniter’s CI_Controller class to get the API’s built-in functionalities.

We define constructor to load our model class. We define the index() function to load the view, where product records are displayed.

The controller class has the required functions to perform CRUD operations on data table.

Therefore we define four methods get_products(), delete_product(), update_product() and add_product() to perform CRUD operations, respectively.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

/**
* Description of BootstrapDatatable_Model
*
* @author https://roytuts.com
*/
class BootstrapDatatable extends CI_Controller {
	
	function __construct() {
        parent::__construct();
        $this->load->model('BootStrapDatatable_Model', 'dm');
    }
	
	function index() {
		$this->load->view('products', NULL);
	}
	
	function get_products() {
		$products = $this->dm->get_products();
		echo json_encode($products);
	}
	
	function delete_product() {
		$id = isset($_POST['id']) ? $_POST['id'] : NULL;
		
		if($this->dm->delete_product($id) === TRUE) {
			return TRUE;
		}
		
		return FALSE;
	}
	
	function update_product() {
		$id = $_POST['id'];
		$name = $_POST['name'];
		$price = $_POST['price'];
		$sale_price = $_POST['sale_price'];
		$sale_count = $_POST['sale_count'];
		$sale_date = $_POST['sale_date'];
		
		if($this->dm->update_product($id, $name, $price, $sale_price, $sale_count, $sale_date) === TRUE) {
			return TRUE;
		}
		
		return FALSE;
	}
	
	function add_product() {
		$name = $_POST['name'];
		$price = $_POST['price'];
		$sale_price = $_POST['sale_price'];
		$sale_count = $_POST['sale_count'];
		$sale_date = $_POST['sale_date'];
		
		if($this->dm->add_product($name, $price, $sale_price, $sale_count, $sale_date) === TRUE) {
			return TRUE;
		}
		
		return FALSE;
	}
}
/* End of file Datatable.php */
/* Location: ./application/controllers/Datatable.php */

Codeigniter View File

Next we need the view file products.php under application/views directory to show data, to update data, to delete data and to add new data.

We include the required JavaScript(JS) and CSS files for the Bootstrap datatable API. We have also included jQuery modal API to create modal window for adding new product.

First we have <p id=’err’/>, where we will show error message when you try to delete a row from the table but unable to delete the row due to any error.

Next we have Add New Product link inside a <p/> tag, clicking on which the form <form id=”add”…/> is opened in a modal window. I have used modal API to use the modal functionalities.

We have defined <table id=”product-grid” …/> to display the data into HTML table using Bootstrap Datatable API.

We define our functions using jQuery API to perform 
CRUD operations.

The code snippets are written under head section under <script/> tag inside $(document).ready(function () { … }).

If you face any error during the row deletion then you will see the error message.

When you edit a particular row you don’t need to show the Edit button. So we are showing Save and Cancel buttons for that row.

You will see error message or success message depending upon whether the edited record gets updated or not.

When you click on the link Add New Product then you will see a modal popup opens with a form to input your product information. You will see success or error message according to your product information saved successfully or not.

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>Bootstrap Datatable CRUD Example using Codeigniter, MySQL, AJAX</title>
	<!--[if IE]> <script> (function() { var html5 = ("abbr,article,aside,audio,canvas,datalist,details," + "figure,footer,header,hgroup,mark,menu,meter,nav,output," + "progress,section,time,video").split(','); for (var i = 0; i < html5.length; i++) { document.createElement(html5[i]); } try { document.execCommand('BackgroundImageCache', false, true); } catch(e) {} })(); </script> <![endif]-->
	<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.css"/>
	<link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css"/>
	<link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.3/css/responsive.bootstrap4.min.css"/>
	<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.2/jquery.modal.min.css"/>
	<script type= 'text/javascript' src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
	<script type= 'text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/jquery-modal/0.9.2/jquery.modal.min.js"></script>
	<script type= 'text/javascript' src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
	<script type= 'text/javascript' src="https://cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js"></script>
	<script type= 'text/javascript' src="https://cdn.datatables.net/responsive/2.2.3/js/dataTables.responsive.min.js"></script>
	<script type= 'text/javascript' src="https://cdn.datatables.net/responsive/2.2.3/js/responsive.bootstrap4.min.js"></script>
	<script type= 'text/javascript'>
		$(document).ready(function () {			
			$('#product-grid').DataTable({
				"processing": true,
				"serverSide": true,
				"ajax": "http://localhost/codeIgniter-3.1.10-bootstrap-datatable/index.php/bootstrapdatatable/get_products",
				columnDefs: [
					{
						targets: 'no-sort', 
						orderable: false 
					}
				]
			});
			
			$(document).delegate('.delete', 'click', function() { 
				if (confirm('Do you really want to delete record?')) {
					var id = $(this).attr('id');
					var parent = $(this).parent().parent();
					$.ajax({
						type: "POST",
						url: "http://localhost/codeIgniter-3.1.10-bootstrap-datatable/index.php/bootstrapdatatable/delete_product",
						data: 'id=' + id,
						cache: false,
						success: function() {
							parent.fadeOut('slow', function() {
								$(this).remove();
							});
						},
						error: function() {
							$('#err').html('<span style=\'color:red; font-weight: bold; font-size: 30px;\'>Error deleting record').fadeIn().fadeOut(4000, function() {
								$(this).remove();
							});
						}
					});
				}
			});
			
			$(document).delegate('.edit', 'click', function() {
				var parent = $(this).parent().parent();
				
				var id = parent.children("td:nth-child(1)");
				var name = parent.children("td:nth-child(2)");
				var price = parent.children("td:nth-child(3)");
				var sale_price = parent.children("td:nth-child(4)");
				var sale_count = parent.children("td:nth-child(5)");
				var sale_date = parent.children("td:nth-child(6)");
				var buttons = parent.children("td:nth-child(7)");
				
				name.html("<input type='text' id='txtName' value='"+name.html()+"'/>");
				price.html("<input type='text' id='txtPrice' value='"+price.html()+"'/>");
				sale_price.html("<input type='text' id='txtSalePrice' value='"+sale_price.html()+"'/>");
				sale_count.html("<input type='text' id='txtSaleCount' value='"+sale_count.html()+"'/>");
				sale_date.html("<input type='text' id='txtSaleDate' value='" + sale_date.html()+"'/>");
				buttons.html("<button class='save'>Save</button>  <button class='cancel'>Cancel</button>");
			});
			
			$(document).delegate('.cancel', 'click', function() {
				var parent = $(this).parent().parent();
				
				var id = parent.children("td:nth-child(1)");
				var name = parent.children("td:nth-child(2)");
				var price = parent.children("td:nth-child(3)");
				var sale_price = parent.children("td:nth-child(4)");
				var sale_count = parent.children("td:nth-child(5)");
				var sale_date = parent.children("td:nth-child(6)");
				var buttons = parent.children("td:nth-child(7)");
				
				name.html(name.children("input[type=text]").val());
				price.html(price.children("input[type=text]").val());
				sale_price.html(sale_price.children("input[type=text]").val());
				sale_count.html(sale_count.children("input[type=text]").val());
				sale_date.html(sale_date.children("input[type=text]").val());
				buttons.html("<button class='edit'>Edit</button>  <button class='delete' id='" + id.html() + "'>Delete</button>");
			});
			
			$(document).delegate('.save', 'click', function() {
				var parent = $(this).parent().parent();
				
				var id = parent.children("td:nth-child(1)");
				var name = parent.children("td:nth-child(2)");
				var price = parent.children("td:nth-child(3)");
				var sale_price = parent.children("td:nth-child(4)");
				var sale_count = parent.children("td:nth-child(5)");
				var sale_date = parent.children("td:nth-child(6)");
				var buttons = parent.children("td:nth-child(7)");
				
				$.ajax({
					type: "POST",
					url: "http://localhost/codeIgniter-3.1.10-bootstrap-datatable/index.php/bootstrapdatatable/update_product",
					data: 'id=' + id.html() + '&name=' + name.children("input[type=text]").val() + '&price=' + price.children("input[type=text]").val() + '&sale_price=' + sale_price.children("input[type=text]").val() + '&sale_count=' + sale_count.children("input[type=text]").val() + '&sale_date=' + sale_date.children("input[type=text]").val(),
					cache: false,
					success: function() {
						name.html(name.children("input[type=text]").val());
						price.html(price.children("input[type=text]").val());
						sale_price.html(sale_price.children("input[type=text]").val());
						sale_count.html(sale_count.children("input[type=text]").val());
						sale_date.html(sale_date.children("input[type=text]").val());
						buttons.html("<button class='edit' id='" + id.html() + "'>Edit</button>  <button class='delete' id='" + id.html() + "'>Delete</button>");
					},
					error: function() {
						$('#err').html('<span style=\'color:red; font-weight: bold; font-size: 30px;\'>Error updating record').fadeIn().fadeOut(4000, function() {
							$(this).remove();
						});
					}
				});
			});
			
			$(document).delegate('#addNew', 'click', function(event) {
				event.preventDefault();
				
				var str = $('#add').serialize();
				
				$.ajax({
					type: "POST",
					url: "http://localhost/codeIgniter-3.1.10-bootstrap-datatable/index.php/bootstrapdatatable/add_product",
					data: str,
					cache: false,
					success: function() {
						$("#msgAdd").html( "<span style='color: green'>Product added successfully</span>" );
					},
					error: function() {
						$("#msgAdd").html( "<span style='color: red'>Error adding a new product</span>" );
					}
				});
			});
		});
	</script>
	
	<style>		
		/* modal window */
		.modal p { margin: 1em 0; }
		
		.add_form.modal {
		  border-radius: 0;
		  line-height: 18px;
		  padding: 0;
		  font-family: "Lucida Grande", Verdana, sans-serif;
		}
		.add_form h3 {
		  margin: 0;
		  padding: 10px;
		  color: #fff;
		  font-size: 14px;
		  background: -moz-linear-gradient(top, #2e5764, #1e3d47);
		  background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #1e3d47),color-stop(1, #2e5764));
		}
		.add_form.modal p { padding: 20px 30px; border-bottom: 1px solid #ddd; margin: 0;
		  background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #eee),color-stop(1, #fff));
		  overflow: hidden;
		}
		.add_form.modal p:last-child { border: none; }
		.add_form.modal p label { float: left; font-weight: bold; color: #333; font-size: 13px; width: 110px; line-height: 22px; }
		.add_form.modal p input[type="text"],
		.add_form.modal p input[type="submit"]		{
		  font: normal 12px/18px "Lucida Grande", Verdana;
		  padding: 3px;
		  border: 1px solid #ddd;
		  width: 200px;
		}
		
		#msgAdd {
		  margin: 10px;
		  padding: 30px;
		  color: #fff;
		  font-size: 18px;
		  font-weight: bold;
		  background: -moz-linear-gradient(top, #2e5764, #1e3d47);
		  background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #1e3d47),color-stop(1, #2e5764));
		}
	</style>
</head>
<body>
	<p id='err'/>
	<p><a class='btn' href="#add" rel="modal:open">Add New Product</a></p>
	<table id="product-grid" class="table table-striped table-bordered dt-responsive nowrap" cellspacing="0" width="99%" style="margin: auto;">
		<thead>
			<tr>
				<th>Id</th>
				<th>Name</th>
				<th>Price</th>
				<th>Sale Price</th>
				<th>Sale Count</th>
				<th>Sale Date</th>
				<th class="no-sort">Actions</th>
			</tr>
		</thead>
	</table>
	
	<form id="add" action="#" class="add_form modal" style="display:none;">
		<div id='msgAdd'/>
		<h3>Add New Product</h3>
		<p>
			<label>Name</label>
			<input type="text" name="name">
		</p>
		<p>
			<label>Price</label>
			<input type="text" name="price">
		</p>
		<p>
			<label>Sale Price</label>
			<input type="text" name="sale_price">
		</p>
		<p>
			<label>Sale Count</label>
			<input type="text" name="sale_count">
		</p>
		<p>
			<label>Sale Date</label>
			<input type="text" name="sale_date">
		</p>
		<p>
			<input type="submit" id="addNew" value="Submit">
		</p>
	</form>
</body>
</html>

Configuring Route

We need to replace our default controller in application/config/routes.php file as shown below:

$route['default_controller'] = 'bootstrapdatatable';

That’s all about our coding part. Now let’s move on to test our application.

Testing the application

Make sure you run the apache http 2.4 server and MySQL server to test the application.

Hit the URL http://localhost/codeIgniter-3.1.10-bootstrap-datatable in the browser to get the home page on browser.

When your home page is open in the browser you will the page looks similar to the below image.

In this page you can search for a particular product, edit an existing product, delete an existing product, add a new product.

bootstrap datatable crud using codeigniter mysql ajax

When you delete a record, you will get a popup to confirm the deletion. If you press OK then record will be deleted else no.

In this functionality the data gets deleted from the database table first and then the particular row gets deleted from the table.

When you click on Edit button you will see all cells in a particular row get edited with existing values in the input fields. You can change only the field value you want to change, then click on the save button. Here also the record gets saved into database table first then the updated values get reflected on the row.

When you click on Add New Product link you will see a modal window gets open with input fields, where you need to input values and click on the submit button to save the new record.

You will get success or error message depending upon whether the record saved successfully or not.

bootstrap datatable crud using codeigniter mysql ajax

Hope, you got idea how to create Bootstrap Datatable CRUD using Codeigniter, MySQL and AJAX.

Source Code

download source code

Thanks for reading.

1 thought on “Bootstrap Datatable CRUD using Codeigniter, MySQL, AJAX

  1. Hello, thanks for the tutorial! This is exactly what I needed :)

    I’ve a question: My table is hiding some columns. But I can access them by clicking the + inside the id cell (master detail). But I don’t know how to disable this.

    Would be nice, If you have a solution for that.

    thanks

Leave a Reply

Your email address will not be published. Required fields are marked *