Can't get Datatables row group working with ajax - javascript

I am trying to group rows in my table based on date ranges using the first column's data("Due_Date") and using the rowGroup extension from Datatables. I have searched and tried solutions from others such as using the data property('Due_Date') vs. the index of an array([0]) and removed buttons from table to prevent conflicts. I believe the versions of jQuery, Datatables, and rowGroup extensions are correct. I actually need the table to be split into three groups(red, yellow, and green) based on the table legend.(If "Due_Date" is before, current date, the current date, or 1 or 2 days after the current date, the group = red group. 3-4 days after current date = yellow group, and 5 or more days after current date = green group.) I realize I don't have the correct logic for the grouped date ranges but as of now I can't get the table to group by the data property at all. The table displays data but it seems as if the grouping is being ignored? Apologies in advance, I'm new to this and not sure where I'm going wrong. Any help is appreciated. Here is my relevant code:
//html
<table class="table table-striped" id="circuitsDueTable">
<caption style="caption-side:top">
<ul>
<li><span style="background-color:#ff3333;font-weight:bolder">RED</span> = Current
Date: Plus Two Days</li>
<li><span style="background-color:#ffff4d;font-weight:bolder">YELLOW</span> =
Pending: Three to Four Days</li>
<li><span style="background-color:#4dff4d;font-weight:bolder">GREEN</span> = Have
Time: Five or More Days</li>
</ul>
</caption>
<thead>
<tr>
<th>OCV DUE DATE</th>
<th>CIRCUIT NAME</th>
<th>OCV</th>
<th>CIRCUIT VIEW</th>
</tr>
</thead>
<tbody id="circuitsDueTableBody"></tbody>
<tfoot></tfoot>
</table>
//javascript/jquery
function getTable() {
$.ajax({
url: baseUrl + "VoltReading/GetOCVDue",
method: "POST",
dataType: "json",
success: function(data) {
if (circuitsDueTable) {
circuitsDueTable.destroy();
}
circuitsDueTable = $("#circuitsDueTable").DataTable({
data: data,
order: [
[0, "asc"]
],
rowGroup: {
dataSrc: "Due_Date"
},
columns: [{
data: 'Due_Date'
},
{
data: 'Circuit_Num'
},
{
data: 'Stage_Num'
},
{
render: function(data, type, row) {
return '<button class="btn btn-success btn-xs viewCircuitBtn"
value="' + row.Circuit_Id + '">View Circuit</button></a>';
}
}
],
//return moment(row.Due_Date).format();
});
}
});
}
getTable()
//php controller
public function GetOCVDue()
{
$ocvsDue = $this->ocv->SelectCircuitOCVDates();
echo json_encode($ocvsDue);
}
//json data
[
{"Circuit_Id":"89","Circuit_Num":"090622002C","Due_Date":"2022-09-10","Stage_Num":"1"},
{"Circuit_Id":"90","Circuit_Num":"0909221B","Due_Date":"2022-09-13","Stage_Num":"1"},
{"Circuit_Id":"89","Circuit_Num":"090622002C","Due_Date":"2022-09-14","Stage_Num":"2"},
{"Circuit_Id":"90","Circuit_Num":"0909221B","Due_Date":"2022-09-17","Stage_Num":"2"},
{"Circuit_Id":"88","Circuit_Num":"090622001B","Due_Date":"2022-09-22","Stage_Num":"3"},
{"Circuit_Id":"89","Circuit_Num":"090622002C","Due_Date":"2022-09-22","Stage_Num":"3"},
{"Circuit_Id":"90","Circuit_Num":"0909221B","Due_Date":"2022-09-25","Stage_Num":"3"}
]

Here is a basic approach - I say "basic" because it does not use a library such as Moment or the newer Luxon - but only the built-in Date object:
var today = new Date();
var redDate = today.setDate(today.getDate() + 2);
var yellowDate = today.setDate(today.getDate() + 4);
I use the above dates to calculate a status color for each record, and I add that status value to the JSON results returned from the URL.
Then, I use the rowGroup.dataSrc option to base its grouping on this newly calculated status color:
rowGroup: {
dataSrc: "status"
}
The full JavaScript is as follows:
$(document).ready(function() {
function getTable() {
$.ajax({
url: "YOUR URL GOES HERE", // I used my own test URL
method: "POST",
dataType: "json",
success: function(data) {
if (circuitsDueTable) {
//circuitsDueTable.destroy();
}
var today = new Date();
var redDate = today.setDate(today.getDate() + 2);
var yellowDate = today.setDate(today.getDate() + 4);
data.forEach(function(row) {
var date = Date.parse(row.Due_Date);
var color = 'green'; // default for 5 or more days
if ( date <= redDate ) {
color = 'red';
} else if ( date <= yellowDate ){
color = 'yellow';
}
row['status'] = color; // add color to row
});
circuitsDueTable = $("#circuitsDueTable").DataTable({
data: data,
order: [
[0, "asc"]
],
rowGroup: {
dataSrc: "status"
},
columns: [{
data: 'Due_Date'
},
{
data: 'Circuit_Num'
},
{
data: 'Stage_Num'
},
{
render: function(data, type, row) {
return '<button class="btn btn-success btn-xs viewCircuitBtn" value="' + row.Circuit_Id + '">View Circuit</button></a>';
}
}
],
//return moment(row.Due_Date).format();
});
}
});
}
getTable()
} );
And the resulting table looks like this:

Related

jQuery calculation in table td loop

I am getting the JSON data through PHP. I am trying to calculate the value of td with the help of javascript and jQuery and calculate the opening and closing balance as below like the table example.
is this possible to do that?
Please help me How I implement with jquery in my jQuery code.
Example table -
open bal as 0 first time + today in - today out = closing bal and
previous closing bal will be open bal next day.
open bal
today in
today out
closing bal
1
1
1
1
2
0
1
1
0
2
0
2
$.ajax({
type: "POST",
cache: false,
},
success: function(response) {
if (response == "ok") {
$.each(response.data, function(i, items) {
tableWithHeader.find('tbody').append(`
<tr>
<td>0</td>
<td>${items.inqty}</td>
<td>${items.outqty}</td>
<td></td>
</tr>
`);
});
}
});
Here:
$.ajax({
type: "POST",
cache: false,
},
success: function(response) {
if (response == "ok") {
let openqty = 0 // declare outside of loop
let closeqty = 0 // declare outside of loop
$.each(response.data, function(i, items) {
closeqty = parseInt(items.inqty) - parseInt(items.outqty) + openqty
//calculate closeqty
tableWithHeader.find('tbody').append(`
<tr>
<td>${openqty}</td> // this will be 0 on first run
<td>${items.inqty}</td>
<td>${items.outqty}</td>
<td>${closeqty}</td>
</tr>
`);
});
openqty = closeqty // now set it for next loop to be same as closeqty
}
});
Working example:
//$.ajax({
//type: "POST",
//cache: false,
//},
//success: function(response) {
//if (response == "ok") {
let openqty = 0 // declare outside of loop
let closeqty = 0 // declare outside of loop
const response = {
data: [{
inqty: "2",
outqty: "0"
}, {
inqty: "0",
outqty: "1"
}, {
inqty: "1",
outqty: "1"
}]
} // sample data
$.each(response.data, function(i, items) {
closeqty = parseInt(items.inqty) - parseInt(items.outqty) + openqty
//calculate closeqty
$("table").find('tbody').append(`
<tr>
<td>${openqty}</td> // this will be 0 on first run
<td>${items.inqty}</td>
<td>${items.outqty}</td>
<td>${closeqty}</td>
</tr>
`);
openqty = closeqty // now set it for next loop to be same as closeqty
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
</tbody>
</table>

How to make datatable specific column editable?

There are various questions put up on this topic but I do not understand them so can anyone help
here is my js code
$(document).ready(function () {
$('#myModal').toggle();
var List = [];
$.ajax({
url: '/urls/' + id,
type: 'POST',
dataType: "json",
data: 'data',
success: function (data) {
console.log("data length: ", data.length);
console.log("data : ", data);
for (var i = 0; i < data.length; i++) {
var Logs = {};
Logs.Info = data[i].Info;
for (var j = 0; j < Logs.Info.length; j++) {
var emplist = {};
emplist.Name = Logs.Info[j].Name;
emplist.dates = Logs.Info[j].dates;
for (var k = 0; k < emplist.dates.length; k++) {
var datelist = {};
datelist.Name = emplist.Name;
datelist.startDate = emplist.dates[k].startDate;
datelist.endDate = emplist.dates[k].endDate;
List.push(datelist);
}
}
}
emptablee = $('#Table').DataTable({
"data": List,
"columns": [
{"data": "Name"},
{"data": "startDate"},
{"data": "endDate"},
],
destroy: true,
"scrollY": "200px",
"scrollCollapse": true,
"paging": false
});
/*emptablee.destroy();*/
}
});
$("#close").on('click', function () {
$("#myModal").hide();
});
});
There are three columns in the table and I want to make a specific columns cell-like editable and show an input box and get the value edited to send.
For anyone checking this now, I've created a custom example in which you can make any column editable by just sending it in a metadata request from serverside.
here : https://github.com/sinhashubh/datatable-examples
If you want, for example, your startDate column to be editable, you need to init the Datatables like this so you can hit the column by class name:
{"data": "startDate", "className": "editable"},
then, with proper event handling
// Activate an inline edit on click of a table cell
$('#Table').on( 'click', 'tbody td.editable', function (e) {
editor.inline( this );
} );
and initializing Editor you will be good:
editor = new $.fn.dataTable.Editor( {
ajax: "../ajax/handle-data.php", // path to back-end data handling
table: "#Table",
fields: [ {
label: "Start Date:",
name: "startDate"
}
]
} );
Also, don't forget to add this outside of document ready handler because you need it as a global var:
var editor;
Full example here (note that Datatables Editor feature is not free) https://editor.datatables.net/examples/inline-editing/columns.html
You can also code up your own completely free version, which is slightly more complicated, without using Editor, but still using class names so you can trigger on click events for specific columns.

Large amount of events loaded on the angularjs-bootstrap-calendar

I'm pulling in ALL my event data from my server and since I have a lot of events to pull, the angular-bootstrap-calendar takes a lot of time to load.
I was wondering if its possible to pull only a month's worth of data for the current view I'm in (month, week, day..I would hide the year view). As I change the view to the next month, I'd pull the data for that month only.
Right now, I pull ALL the data only once, when the calendar loads, but not sure how to pull the data when the view changes.
var urlapievents = $location.protocol() + "://" + $location.host() + "/api/events/" ;
$http.get(urlapievents).success(function(events) {
Good solution for me
Get year and month of view, send it to API, and only retrieve events for that year-month:
js
vm.viewChangeClicked = function() {
var viewDateYearMonth = moment(vm.viewDate).format('YYYY-MM');
var urlapieventsall = $location.protocol() + "://" + $location.host() + "/api/events/" + viewDateYearMonth ;
$http.get(urlapieventsall).success(function(events) {
vm.events = events.events;
});
};
html
<div class="col-md-6 text-center">
<div class="btn-group">
<label class="btn btn-primary" ng-model="vm.calendarView" uib-btn-radio="'month'" ng-click="vm.cellIsOpen = false; vm.viewChangeClicked()">Month</label>
<label class="btn btn-primary" ng-model="vm.calendarView" uib-btn-radio="'week'" ng-click="vm.cellIsOpen = false; vm.viewChangeClicked()">Week</label>
<label class="btn btn-primary" ng-model="vm.calendarView" uib-btn-radio="'day'" ng-click="vm.cellIsOpen = false; vm.viewChangeClicked()">Day</label>
</div>
</div>
I've also added logic to check if previous yyyy-mm is equal to current yyyy-mm to save some unnecessary calls to the API.
If you grab your events as a json feed, you can use additional options - startParam and endParam. They can be used like this:
$('#calendar').fullCalendar({
events: function(start, end, timezone, callback) {
if (request) {
request.abort();
};
$.mobile.loading('show');
request = $.ajax({
type: "POST",
url: "../Services/Calendar/CalendarService.asmx/GetEvents",
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: "{ dtStart: " + JSON.stringify(start) + ", dtEnd: " + JSON.stringify(end) + "}",
success: function(data) {
var events1 = [];
$(data.d).each(function() {
events1.push({
title: this.Title,
start: this.Start,
end: this.End,
id: this.Id
});
});
callback(events1);
$.mobile.loading('hide');
},
error: function(jqXHR, textStatus, errorThrown) {
if (jqXHR.statusText == 'abort') {
$.mobile.loading('hide');
return;
} else {
alert('There was an error');
$.mobile.loading('hide');
}
}
});
}
});
You can read more about those parameters here: https://fullcalendar.io/docs/event_data/events_json_feed/
The functionality you describe is a sort of date pagination, although this functionality isn't built in (shame, because it sounds really useful), you can implement your own with some small amount of work
First, the datepicker stores a JS Date object inside the ng-model, you can $watch it and get the current year/month/day out of it
$scope.modelDate = new Date()
...
$scope.$watch('modelDate', function(newDate, oldDate) {
newDate.getDay(); // 5
newDate.getMonth(); // 11
newDate.getYear(); // 116
})
Now you can query your database to get all the event for your selected month
Also, you can utilize the datepicker's mode (showing wether you are viewing the datepicker in the day/month/year mode, you set it up inside the options object).
datepickerMode C (Default: day) - Current mode of the datepicker (day|month|year). Can be used to initialize the datepicker in a specific mode.
Using this property you can query a month, year or years of events.

Get Dynatables to modify thead headers after a JSON call

I have an ajax backed dynatable. At the moment, it works perfectly for tables with known headers prior.
Example:
var tableHeaders = '';
// Generate table headers from some list
$scope.Model.computed.selection_list.map(
function(selection){
column_name = selection.table + "." + selection.column;
tableHeaders += "<th>" + column_name + "</th>";
});
//wipe div hosting the dynatable and reinitialise a table
var table_div = $('#TableDiv');
table_div.empty();
table_div.append('<table id="previewTable" class="table table-condensed table-responsive table-striped table-hover"><thead><tr>' + tableHeaders + '</tr></thead></table>');
var preview_table = $('#previewTable');
console.log("Table wiped");
//initialise the dynatable
preview_table.dynatable({
features: {
perPageSelect: true,
search: false
},
table: {
defaultColumnIdStyle: 'underscore',
headRowSelector:'thead tr',
headRowClass: ''
},
dataset: {
ajax: true,
ajaxUrl: data_url,
ajaxOnLoad: false,
ajaxMethod: 'POST',
records: []
}
});
However, I'd like to have the table headers generated after fetching the records but prior to filling out the rows.
Is this possible?
// Changing via an ajax success event hook doesn't work.
// The table headers change but the records don't bind to the correct column leaving every row as null
preview_table.bind('dynatable:ajax:success', function(e, response){
console.log("Ajax response: " + response) ;
tableHeaders = '';
first_record = response.records[0];
Object.keys(first_record).map(function(column_name){
tableHeaders += "<th>" + column_name + "</th>";
}
)
preview_table.html('<thead><tr>' + tableHeaders + '</tr></thead>')
console.log("headers: " + tableHeaders);
})
I had exactly the same problem and after hours of struggling I came up with this solution:
First, your initial TABLE should look like this:
<table id="my-table">
<thead>
<tr><th></th></tr>
</thead>
<tbody>
</tbody>
</table>
We need the empty TH to prevent the plugin from throwing an error (Couldn't find any columns headers in...), it will be removed later.
Then we use the dynatable:ajax:success to edit the columns as follow:
$("#my-table").one('dynatable:ajax:success', function(e, response){
//Get dynatable
var dynatable = $(this).data('dynatable');
//Remove the empty column
dynatable.domColumns.remove(0);
//Add new columns
var pos = 0;
for(var column in response.records[0]) {
dynatable.domColumns.add($('<th>'+column+'</th>'), pos++);
}
});
Finally, you can initiate the plugin:
$("#my-table").dynatable({
features: {
perPageSelect: true,
search: false
},
table: {
defaultColumnIdStyle: 'underscore',
headRowClass: ''
},
dataset: {
ajax: true,
ajaxUrl: data_url,
ajaxOnLoad: false,
records: []
}
});
Check the following demo, please note that the snippet is not fully functional it throws (SecurityError). Here is a fully working jsfiddle:
var data_url = "https://gist.githubusercontent.com/iRbouh/47a9fb7e5f6a79e0f4b0e7e8a837a825/raw/6adbba47bfbf9453c50f9710f77c71e69f683139/sample-data.json";
var preview_table = $('#my-table');
preview_table.one('dynatable:ajax:success', function(e, response){
//Get dynatable
var dynatable = $(this).data('dynatable');
//Remove init column
dynatable.domColumns.remove(0);
//Add new columns
var pos = 0;
for(var column in response.records[0]) {
dynatable.domColumns.add($('<th>'+column+'</th>'), pos++);
}
});
preview_table.dynatable({
features: {
perPageSelect: true,
search: false
},
table: {
defaultColumnIdStyle: 'underscore',
headRowClass: ''
},
dataset: {
ajax: true,
ajaxUrl: data_url,
ajaxOnLoad: false,
records: []
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<link href="https://cdn.rawgit.com/alfajango/jquery-dynatable/master/jquery.dynatable.css" rel="stylesheet"/>
<script src="https://cdn.rawgit.com/alfajango/jquery-dynatable/master/jquery.dynatable.js"></script>
<table id="my-table">
<thead>
<tr><th></th></tr>
</thead>
<tbody>
</tbody>
</table>

How to get the data from ajax in controller codeigniter

I have an editable table in my view.. At first, there's no data in the table but the user can add data in the table since it is editable. And there's no exact number of rows in the table since I have also a button that can add new row. I want to get the data that the user have added and save it in the database.
I have this code:
VIEW:
<table class="table " id="memberTB">
<thead><tr><th >First Name</th><th >Middle Name</th><th>Last Name</th></tr></thead>
<tbody>
<tr id="first"><td><span class="edit"></span></td>
<td><span class="edit"></span></td>
<td><span class="edit"></span></td></tr>
</tbody>
<button type="button" class="btn btn-link" id="addrow"><span class="fa fa-plus"> Add new row</span></button>
</table>
<br><button type="button" class="btn" id="savebtn">Save</button> Reset
JS:
$.fn.editable.defaults.mode = 'inline';
$.fn.editable.defaults.showbuttons = false;
$.fn.editable.defaults.url = '/post';
$.fn.editable.defaults.type = 'text';
// make all items having class 'edit' editable
$('.edit').editable();
// this is to automatically make the next item in the table editable
$('.edit').on('save', function(e, params){
var that = this;
// persist the old value in the element to be restored when clicking reset
var oldItemValue = $(that)[0].innerHTML;
if (!$(that).attr('oldValue')) {
console.log('persisting original value: ' + oldItemValue)
$(that).attr('oldValue', oldItemValue);
}
setTimeout(function() {
// first search the row
var item = $(that).closest('td').next().find('.edit');
console.log(item);
if (item.length == 0) {
// check the next row
item = $(that).closest('tr').next().find('.edit');
}
item.editable('show');
}, 200);
});
$('#resetbtn').click(function() {
$('.edit').each(function() {
var o = $(this);
o.editable('setValue', o.attr('oldValue')) //clear values
.editable('option', 'pk', o.attr('pk')) //clear pk
.removeClass('editable-unsaved')
.removeAttr('oldValue');
});
});
$('#savebtn').click(function() {
var person = [];
var x=1;
$('tbody tr',$('#memberTB')).each(function(){
for(var i = 0 ; i < cells ; i++)
{
person[x][i]=$(this).find('td').eq(i).text();
}
x++;
});
$.ajax({
url: '<?php echo base_url("index.php/test/Savedata");?>',
type: "post",
data: { values: arraylng },
cache: false,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
}
});
});
$('#addrow').click(function() {
$('#memberTB > tbody:last').append(' <tr><td><span class="edit"></span></td><td><span class="edit"></span></td><td><span class="edit"></span></td></tr>');
$('.edit').editable();
});
Controller: [inside the test.php]
public function saveData(){
$this->load->model('test_model');
$myArray = $_REQUEST['values'];
echo sizeof($myArray);
}
Whenever I click the save button, there's no response at all.. Where did I go wrong? please help me..
ADDED INFO:
I didn't include my SQL insert statement here because I want to test first if there's data in $myArray if I added data in the table.
Better use this ajax
var arraylng = [3,4,7];
$.ajax({
url: '<?php echo base_url("index.php/test/Savedata");?>',
type: "post",
data: {values: JSON.stringify(arraylng)},
cache: false,
success: function (response) {
alert(response);
}
});
arraylng is an array, which doesn't exist in the code. I added it here for debugging.
Suppose you want to send person[] array, you write, data: {values: JSON.stringify(person)}.
Now, the person array may not exist, because of the "i < cells" in for. What is cells?
The word response is just a name, any name, but better avoid 'data'.
In test.php, what is sizeof($myArray)? Just, echo $myArray;
When you click save you must get the $myArray content in an alert.

Categories

Resources