I want to populate a jQuery datatable based on the content of a textarea. Note: my datatables implementation is not serverside. That is: sorting/filtering happens on the client.
I know my php works as it returns expected results in my test scenario (see below). I have included a lot of code to provide context. I am new to datatables and php.
My html looks like this:
// DataTable Initialization
// (no ajax yet)
$('#selectedEmails').DataTable({
select: {
sytle: 'multiple',
items: 'row'
},
paging: false,
scrollY: '60vh',
scrollCollapse: true,
columns: [
{data: "CONICAL_NAME"},
{data: "EMAIL_ADDRESS"}
]
});
// javascript that defines the ajax (called by textarea 'onfocus' event)
function getEmails(componentID) {
deselectTabs();
assignedEmails = document.getElementById(componentID).value.toUpperCase().split(",");
alert(JSON.stringify(assignedEmails)); //returns expected json
document.getElementById('email').style.display = "block";
//emailTable = $('#selectedEmails').DataTable();
try {
$('#selectedEmails').DataTable().ajax =
{
url: "php/email.php",
contentType: "application/json",
type: "POST",
data: JSON.stringify(assignedEmails)
};
$('#selectedEmails').DataTable().ajax.reload();
} catch (err) {
alert(err.message); //I get CANNOT SET PROPERTY 'DATA' OF null
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- table skeleton -->
<table id="selectedEmails" class="display" style="width: 100%">
<thead>
<tr>
<th colspan='2'>SELECTED ADDRESSES</th>
</tr>
<tr>
<th>Conical Name</th>
<th>Email Address</th>
</tr>
</thead>
</table>
<!-- textarea definition -->
<textarea id='distribution' name='distribution' rows='3'
style='width: 100%' onblur="validateEmail('INFO_DISTRIBUTION', 'distribution');"
onfocus="getEmails('distribution');">
</textarea>
The following code returns the expected json:
var url = "php/email.php";
emailList = ["someone#mycompany.com","someoneelse#mycompany.com"];
fetch(url, {
method: 'post',
body: JSON.stringify(emailList),
headers: {
'Content-Type': 'application/json'
}
}).then(function (response) {
return response.text();
}).then(function (text) {
alert( JSON.stringify( JSON.parse(text))); //expencted json
}).catch(function (error) {
alert(error);
});
php code:
require "openDB.php";
if (!$ora) {
$rowsx = array();
$rowx = array("CONICAL_NAME" => "COULD NOT CONNECT", "EMAIL_ADDRESS" => "");
$rowsx[0] = $rowx;
echo json_encode($rowsx);
} else {
//basic query
$query = "SELECT CONICAL_NAME, EMAIL_ADDRESS "
. "FROM SCRPT_APP.BCBSM_PEOPLE "
. "WHERE KEY_EMAIL LIKE '%#MYCOMANY.COM' ";
//alter query to get specified entries if first entry is not 'everybody'
if ($emailList[0]!='everybody') {
$p = 0;
$parameters = array();
foreach ($emailList as $email) {
$parmName = ":email" . $p;
$parmValue = strtoupper(trim($email));
$parameters[$p] = array($parmName,$parmValue);
$p++;
}
$p0=0;
$query = $query . "AND KEY_EMAIL IN (";
foreach ($parameters as $parameter) {
if ($p0 >0) {
$query = $query.",";
}
$query = $query.$parameter[0];
$p0++;
}
$query = $query . ") ";
$query = $query . "ORDER BY CONICAL_NAME";
$getEmails = oci_parse($ora, $query);
foreach ($parameters as $parameter) {
oci_bind_by_name($getEmails, $parameter[0], $parameter[1]);
}
}
oci_execute($getEmails);
$row_num = 0;
try {
while (( $row = oci_fetch_array($getEmails, OCI_ASSOC + OCI_RETURN_NULLS)) != false) {
$rows[$row_num] = $row;
$row_num++;
}
$jsonEmails = json_encode($rows, JSON_INVALID_UTF8_IGNORE);
if (json_last_error() != 0) {
echo json_last_error();
}
} catch (Exception $ex) {
echo $ex;
}
echo $jsonEmails;
oci_free_statement($getEmails);
oci_close($ora);
}
Looking at a couple of examples on the DataTables site, I found I was making this more difficult than it needed to be: Here is my solution:
HTML: (unchanged)
<table id="selectedEmails" class="display" style="width: 100%">
<thead>
<tr>
<th colspan='2'>SELECTED ADDRESSES</th>
</tr>
<tr>
<th>Conical Name</th>
<th>Email Address</th>
</tr>
</thead>
</table>
<textarea id='distribution' name='distribution' rows='3'
style='width: 100%'
onblur="validateEmail('INFO_DISTRIBUTION', 'distribution');"
onfocus="getEmailsForTextBox('distribution');">
</textarea>
javascript:
Note: The key was the function for data: which returns json. (My php code expects json as input, and of course, outputs json).
[initialization]
var textbox = 'developer'; //global variable of id of textbox so datatables can use different textboxes to populate table
$(document).ready(function () {
$('#selectedEmails').DataTable({
select: {
sytle: 'multiple',
items: 'row'
},
ajax: {
url: "php/emailForList.php",
contentType: "application/json",
type: "post",
data: function (d) {
return JSON.stringify(document.getElementById(textbox).value.toUpperCase().split(","));
},
dataSrc: ""
},
paging: false,
scrollY: '60vh',
scrollCollapse: true,
columns: [
{data: "CONICAL_NAME"},
{data: "EMAIL_ADDRESS"}
]
});
});
[code that redraws table]
function getEmailsForTextBox(componentID) {
deselectTabs();
document.getElementById('email').style.display = "block";
textbox = componentID; //textbox is global variable that DataTable uses as source control
$('#selectedEmails').DataTable().ajax.reload();
}
Related
I have private variable in codeigniter like this :
private $table = 'phone';
private $column_order = array(null, 'name', 'price');
private $type = array('type');
private $battery_consumption = array('battery_consumption');
And I want using my variable in my private model :
private get_data_query(){
$this->db->select($this->column_order);
$this->db->select_sum($this->battery_consumption);
$this->db->from($this->table);
$this->db->group_by($this->type);
}
And Then I Call that private function into my public function to use fetch my data in the table :
function get_datatables(){
$this->_get_data_query();
if($_POST['length'] != -1)
$this->db->limit($_POST['length'], $_POST['start']);
$query = $this->db->get();
return $query->result();
}
function count_filtered()
{
$this->_get_data_query();
$query = $this->db->get();
return $query->num_rows();
}
public function count_all()
{
$this->db->from($this->table);
return $this->db->count_all_results();
}
In Controller:
public function get_data_phone()
{
$list = $this->m_phone->get_datatables();
$data = array();
$no = $_POST['start'];
foreach ($list as $field) {
$row[] = $no;
$row[] = $field->name;
$row[] = $field->type;
$row[] = $field->price;
$row[] = $field->battery_consumption;
$data[] = $row;
}
$output = array(
"draw" => $_POST['draw'],
"recordsTotal" => $this->m_request->count_all(),
"recordsFiltered" => $this->m_request->count_filtered(),
"data" => $data,
);
echo json_encode($output);
}
In View:
<div class="card-block">
<div class="dt-responsive table-responsive">
<table id="phone" class="ui celled table" style="width:100%">
<thead>
<tr>
<th>No</th>
<th>Phone Name</th>
<th>Phone Type</th>
<th>Phone Price</th>
<th>Battery Health</th>
</tr>
</thead>
</table>
</div>
</div>
Datatable query:
let table;
$(document).ready(function() {
phone_data();
function phone_data() {
table = $('#phone').DataTable({
"processing": true,
"serverSide": true,
"order": [],
"ajax": {
"url": "<?= site_url('phone/get_data_phone') ?>",
"type": "POST",
},
"columnDefs": [{
"targets": [0],
"orderable": false,
}, ],
});
}
});
But My Query in model still error using select_sum(), what sould i do?
For me it seems you forgot a $this in function get_data_query. There's no $battery_consumption array in the function body. And you also didn't put a function keyword there, my PHP IDE marks errors on that even without running anything.
I have an issues with datatable show entries 、sorting and filter basically all the JS function not working. I've already include the JS files. some details:my DataTables is server-side processing and retrieve data in json from serverside .
datatable.php
<script type="text/javascript" charset="utf8" src="//code.jquery.com/jquery-1.12.3.js"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function() {
$.fn.dataTable.ext.errMode = 'none';
var table = $('#example').DataTable( {
"processing": true,
"serverSide": true,
"jQueryUI": true,
"ordering": true,
"searching": true,
"order": [[1, 'desc']],//set column 1 (time)
"ajax": {
url: "process.php",
type: 'POST',
data: {
from: "<?php echo $from; ?>",
to: "<?php echo $to; ?>"
}
},
"columns": [
{
"className":'details-control',
"orderable":false,
"data":null,
"defaultContent": ''
},
{ "data": "time"},
{ "data": "message",
"render": function ( data, type, row )
{
data = data.replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
return type === 'display' && data.length > 200 ?
'<span title="'+data+'">'+data.substr( 0, 98 )+'...</span>' :data;
}
}
]
} );
// Add event listener for opening and closing details
$('#example tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format( row.data())).show();
tr.addClass('shown');
}
} );
} );
</script>
<body>
<table id="example" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th ></th>
<th data-search-index="3">time</th>
<th data-search-index="3">Message</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>time</th>
<th>Message</th>
</tr>
</tfoot>
</table>
</body>
process.php
$search='';
$requestData= $_REQUEST;
if(isset($_POST["search"]["value"]) && !empty($_POST["search"]["value"])){
$search ='&q=_all:'.$_POST["search"]["value"];
}
$qryurl ='<ip>/log/_search?size=10'.$search ;
if ( !empty($requestData['start']) && $requestData['length'] != '-1' )
{
$qryurl ='<ip>/log/_search?size=10&from='.$requestData['start'].$search;
}
.......
//json output
$results = array(
"draw" => intval($requestData['draw']),
"iTotalRecords" =>intval($total),
"iTotalDisplayRecords" => intval($total),
"aaData"=>$sourceary
);
now I can see the table but I just can't sorting or searching and show more entries. any suggestion? Thank a lot, More
I think you need add a objects to your DataTable:
ordering: true,
searching: true,
order: [[0, 'asc']]//default
To your PHP code than you must add something like this for ordering:
if(count($_POST['order'])){
$orderBy = $_POST['columns'][$_POST['order'][0]['column']]['data'];
$orderDir = $_POST['order'][0]['dir'];
}
And for searching:
if(isset($_POST["search"]["value"]) && !empty($_POST["search"]["value"])){
$search = $_POST["search"]["value"];
}
For entries you must put this variables to your url:
$howMany = (isset($_POST['length'])) ? intval($_POST['length']) : 10;//10 is default its size param
$start = (isset($_POST['start'])) ? intval($_POST['start']) : 0;
And put this variables to your query.
i Have used following script, data doesn't load to dataTable, i got error click here to show error image
Here my jquery code
Table = $("#example").DataTable({
data:[],
columns: [
{ "data": "Course" },
{ "data": "Batch" },
{ "data": "Admission No" },
{ "data": "Rollno" },
{ "data": "Student Name" },
{ "data": "Email" }
],
rowCallback: function (row, data) {},
filter: false,
info: false,
ordering: false,
processing: true,
retrieve: true
});
$('.view_search_btn').click(function(){
//alert("clicked");
var search_key = $('input[name=view_stu_search]').val();
$('.box-body').show();
$.ajax({
url: "../live_search.php",
type: "post",
data: "key="+'view_student_search_key'+"&search_keyword="+search_key
}).done(function (result) {
Table.clear().draw();
Table.rows.add(result).draw();
}).fail(function (jqXHR, textStatus, errorThrown) {
// needs to implement if it fails
});
});// Click event close here
}); // document close here
and my php code is
if(!ctype_digit($_POST['search_keyword'])){
//echo "given value is string".$_POST['search_keyword'];
$rows = search_keyword($view_student_search_key);
//print_r($rows);
foreach($rows as $row)
{
$query = "SELECT a.stu_rollno, c.stu_course,c.stu_batch,a.admission_no,p.stu_firstname,p.stu_lastname,co.stu_email FROM current_course c, admission_details a,stu_personal_details p, stu_contact_details co WHERE a.stu_rollno = p.stu_rollno AND c.stu_rollno = co.stu_rollno AND a.stu_rollno = c.stu_rollno AND (c.stu_degree = ".$row['degree_id']." AND c.stu_course = ".$row['course_id']." AND c.stu_branch = ".$row['branch_id'].");";
//echo "<br><br>";
$run_query = mysqli_query($con, $query);
while($result = mysqli_fetch_array($run_query))
{
echo "
<tr>
<td>".$row['course_name']."</td>
<td>".$result['stu_batch']."</td>
<td>".$result['admission_no']."</td>
<td>".$result['stu_rollno']."</td>
<td>".$result['stu_firstname'].$result['stu_lastname']."</td>
<td>".$result['stu_email']."</td>
<td align='center'><a href='edit.php?rollno=".$result['stu_rollno']."°ree=".$row['degree_name']."&course=".$row['course_name']."&branch=".$row['branch_name']."' class='btn btn-info btn-sm btn-flat'><i class='fa fa-edit'></i> Edit</a>
<button type='button' class='btn btn-danger btn-sm btn-flat' name='remove_levels' data-toggle='modal' data-target='.bs-example-modal-sm'><i class='fa fa-close'></i> Delete</button>
</td>
</tr>
";
}
}
}`
this following function inside my php
function search_keyword($view_student_search_key)
{
$query = "SELECT d.degree_id,d.degree_name,c.course_id,c.course_name,b.branch_id,b.branch_name FROM degree d,courses c,branch b WHERE d.degree_id = c.degree_id AND b.course_id = c.course_id AND (d.degree_name like '%$view_student_search_key%' OR c.course_name like '%$view_student_search_key%' OR b.branch_name like '%$view_student_search_key%')";
global $con;
$run_query = mysqli_query($con, $query);
//Declare the rows to an array
$rows = array();
// Insert Each row to an array
while($row = mysqli_fetch_array($run_query))
{
$rows[] = $row;
}
// Return the array
return $rows;
}`
Here, You are adding total 6 td for header and Then for inner tr You are adding 7 td. So there is mismatch in datatable td for each row.
What you can do is:
Just add one more td to your datatable initialization preceding with , (comma):
{ "data": "Actions" }
Note: Action is a title for td of edit & other icons column.
Use xhr.dt and reload data using the datatables load() api.
xhr.dt will listen on the ajax call data when it gets loaded. You can clear and draw i.e append data in the xhr callback function. Hope that helps.
I have a mysql table with about 30000 rows. I have to put all rows in a DataTable and load each segment each time a table page is loaded (when you click on pagination). I saw that I can use the deferLoading parameter in my JS, but when I use it my pages are not loading. As you can see, I have to load images, so I absolutely have to do a light loading of the content...
Here is my HTML :
<table class="table table-striped table-bordered table-hover datatable products-datatable">
<thead>
<tr>
<th></th>
<th><?=_("Product")?></th>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th><?=_("Product")?></th>
<th></th>
</tr>
</tfoot>
</table>
Here is my JS :
var table = $('.products-datatable').dataTable( {
"order": [[ 1, "asc" ]],
"processing": true,
"serverSide": true,
"deferLoading": 30000,
"ajax": {
url: location.protocol + '//' + location.hostname + '/ajax/products.php?action=list',
type: "POST"
},
"columns": [
{ "data": "image",
"orderable": false,
"width": "80px" },
{ "data": "product" },
{ "data": "action",
"orderable": false,
"width": "20px",
"sClass": "class",
}
]
});
Here is my AJAX :
$req = $pdo->prepare('SELECT product_id, name FROM products');
if ( $req->execute() ) {
if ($req->rowCount()) {
$result['draw'] = 1;
$result['recordsTotal'] = $req->rowCount();
$result['recordsFiltered'] = 10;
$result['data'] = array();
$result['DT_RowId'][] = array();
while( $row = $req->fetch() ) {
if ($row['name']) { $name = $row['name']; } else { $name = "N/A"; }
$result['data'][] = array( "DT_RowId" => $row['product_id'],
"DT_RowClass" => 'myclass',
"image" => '<img src="' . HOSTNAME.'assets/img/products/' . $row['product_id'] . '.jpg" class="product_thumb">',
"product" => '' . $name . '',
"action" => "<i class=\"fa fa-close fa-2x text-danger\"></i>"
);
}
}
}
$req->closeCursor();
I'm sure there is something I missed... :-(
I believe you don't need to use deferLoading to benefit from server-side processing.
Your current script just returns all records and doesn't do sorting or filtering. You need to use ssp.class.php (available in DataTables distribution package) or emran/ssp class to correctly handle AJAX requests on the server.
DataTables library will send start and length parameters in AJAX request indicating which portion of the data is needed and your server-side processing class will correctly handle it for you.
Please see an example of server-side processing for more information.
I have been trying to make an autocomplete script for the whole day but I can't seem to figure it out.
<form method="POST">
<input type="number" id="firstfield">
<input type="text" id="text_first">
<input type="text" id="text_sec">
<input type="text" id="text_third">
</form>
This is my html.
what I am trying to do is to use ajax to autocomplete the first field
like this:
and when there are 9 numbers in the first input it fills the other inputs as well with the correct linked data
the script on the ajax.php sends a mysqli_query to the server and asks for all the
data(table: fields || rows: number, first, sec, third)
https://github.com/ivaynberg/select2
PHP Integration Example:
<?php
/* add your db connector in bootstrap.php */
require 'bootstrap.php';
/*
$('#categories').select2({
placeholder: 'Search for a category',
ajax: {
url: "/ajax/select2_sample.php",
dataType: 'json',
quietMillis: 100,
data: function (term, page) {
return {
term: term, //search term
page_limit: 10 // page size
};
},
results: function (data, page) {
return { results: data.results };
}
},
initSelection: function(element, callback) {
return $.getJSON("/ajax/select2_sample.php?id=" + (element.val()), null, function(data) {
return callback(data);
});
}
});
*/
$row = array();
$return_arr = array();
$row_array = array();
if((isset($_GET['term']) && strlen($_GET['term']) > 0) || (isset($_GET['id']) && is_numeric($_GET['id'])))
{
if(isset($_GET['term']))
{
$getVar = $db->real_escape_string($_GET['term']);
$whereClause = " label LIKE '%" . $getVar ."%' ";
}
elseif(isset($_GET['id']))
{
$whereClause = " categoryId = $getVar ";
}
/* limit with page_limit get */
$limit = intval($_GET['page_limit']);
$sql = "SELECT id, text FROM mytable WHERE $whereClause ORDER BY text LIMIT $limit";
/** #var $result MySQLi_result */
$result = $db->query($sql);
if($result->num_rows > 0)
{
while($row = $result->fetch_array())
{
$row_array['id'] = $row['id'];
$row_array['text'] = utf8_encode($row['text']);
array_push($return_arr,$row_array);
}
}
}
else
{
$row_array['id'] = 0;
$row_array['text'] = utf8_encode('Start Typing....');
array_push($return_arr,$row_array);
}
$ret = array();
/* this is the return for a single result needed by select2 for initSelection */
if(isset($_GET['id']))
{
$ret = $row_array;
}
/* this is the return for a multiple results needed by select2
* Your results in select2 options needs to be data.result
*/
else
{
$ret['results'] = $return_arr;
}
echo json_encode($ret);
$db->close();
Legacy Version:
In my example i'm using an old Yii project, but you can easily edit it to your demands.
The request encodes in JSON. (You don't need yii for this tho)
public function actionSearchUser($query) {
$this->check();
if ($query === '' || strlen($query) < 3) {
echo CJSON::encode(array('id' => -1));
} else {
$users = User::model()->findAll(array('order' => 'userID',
'condition' => 'username LIKE :username',
'limit' => '5',
'params' => array(':username' => $query . '%')
));
$data = array();
foreach ($users as $user) {
$data[] = array(
'id' => $user->userID,
'text' => $user->username,
);
}
echo CJSON::encode($data);
}
Yii::app()->end();
}
Using this in the View:
$this->widget('ext.ESelect2.ESelect2', array(
'name' => 'userID',
'options' => array(
'minimumInputLength' => '3',
'width' => '348px',
'placeholder' => 'Select Person',
'ajax' => array(
'url' => Yii::app()->controller->createUrl('API/searchUser'),
'dataType' => 'json',
'data' => 'js:function(term, page) { return {q: term }; }',
'results' => 'js:function(data) { return {results: data}; }',
),
),
));
The following Script is taken from the official documentation, may be easier to adopt to:
$("#e6").select2({
placeholder: {title: "Search for a movie", id: ""},
minimumInputLength: 1,
ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
url: "http://api.rottentomatoes.com/api/public/v1.0/movies.json",
dataType: 'jsonp',
data: function (term, page) {
return {
q: term, // search term
page_limit: 10,
apikey: "ju6z9mjyajq2djue3gbvv26t" // please do not use so this example keeps working
};
},
results: function (data, page) { // parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to alter remote JSON data
return {results: data.movies};
}
},
formatResult: movieFormatResult, // omitted for brevity, see the source of this page
formatSelection: movieFormatSelection // omitted for brevity, see the source of this page
});
This may be found here: http://ivaynberg.github.io/select2/select-2.1.html
You can optain a copy of select2 on the github repository above.