Bootstrap multi row selection from table data and post to Flask backend - javascript

What I want to do is to let my users select multiple rows in a table and them hit a button to send this data back. My JS script file looks has the following:
<script>
$(document).ready(function () {
// Setup - add a text input to each footer cell
$('#example tfoot th').each(function () {
var title = $(this).text();
$(this).html('<input type="text" placeholder="Search ' + title + '" />');
});
$('#example tbody').on('click', 'tr', function () {
$(this).toggleClass('selected');
});
$('#button').click(function () {
alert(table.rows('.selected').data().length + ' row(s) selected');
});
// DataTable
var table = $('#example').DataTable({
initComplete: function () {
// Apply the search
this.api()
.columns()
.every(function () {
var that = this;
$('input', this.footer()).on('keyup change clear', function () {
if (that.search() !== this.value) {
that.search(this.value).draw();
}
});
});
},
});
});
</script>
My HTML code is as follows:
<form action="/get1" method="POST" name = 'input'>
<button id="button">Row count</button>
<table id="example" class="table table-striped">
<thead>
<tr>
<th scope="col">Index</th>
<th scope="col">Col2</th>
<th scope="col">Col3</th>
<th scope="col">Col4</th>
</tr>
</thead>
<tbody>
{% for item in rows %}
<tr>
<td>{{item[0]}}</td>
<td>{{ item[1] }}</td>
<td>{{ item[2] }}</td>
<td>{{ item[3] }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th>Index</th>
<th>Col2</th>
<th>Col3</th>
<th>Col4</th>
</tr>
</tfoot>
</table>
</form>
I need some help with JS and HTML to POST values (such as row index) to the backend that the backend can read.

Let's assume you have added the following DataTables Select resources to the head of your web page:
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.4.0/css/select.dataTables.css"/>
<script type="text/javascript" src="https://cdn.datatables.net/select/1.4.0/js/dataTables.select.js"></script>
Then you can enable the extension by adding the following option to your DataTable:
select: true
Now you can experiment with selecting and de-selecting rows. You can use the CTRL and SHIFT keys to select multiple rows.
In your button click event you can now use the selected() function I mentioned in my comment - for example:
$('#button').click(function () {
selected_ids = [];
table.rows().every(function () {
if ( this.selected() ) {
selected_ids.push( this.data()[0] );
}
});
console.log( selected_ids );
});
This will capture an array of IDs from the selected rows.
Note how it uses very similar logic to the columns().every() function you already have - except it uses rows().every() to iterate over the rows in the DataTable - not only the visible rows in the current page, but also all rows in other DataTables pages (if there multiple pages of table data).
The next step is a completely different question: How to submit the IDs in that array to your Flask back end.
That has been covered elsewhere in various questions - for example: jQuery Ajax POST example with PHP. Yes, this mentions PHP, but the jQuery piece is independent of the server technology.
That question has 25 answers, and there are various other questions along similar lines, which should help you. If you get stuck you can ask a new question with the specific problem you are facing.
But, basically, instead of my console.log( selected_ids );, you would use a jquery Ajax call: $.ajax( { ... } ); to send the data to Flask.

Related

How to call php script with ajax?

I'm trying to create multiple tables where I can move table rows between the tables and have ajax call a php script that updates the DB with the new values, ie the new parent to the row.
It's only html and javascript now and I'm wondering how the ajax part should look like to call a php script that updates the DB? And also if I should make some changes to the javascript/html part?
HTML:
<table class="tables_ui" id="t_draggable1"><h4>Table 1</h4>
<tbody class="t_sortable">
<tr>
<th>Title</th>
<th>Status</th>
<th>Creation date</th>
</tr>
#foreach($tasks as $task)
<tr class="row1" data-id="{{ $task->id }}">
<td>{{ $task->title }}</td>
<td>{{ ($task->status == 1)? "Completed" : "Not Completed" }}</td>
<td>{{ date('d-m-Y h:m:s',strtotime($task->created_at)) }}</td>
</tr>
#endforeach
</tbody>
</table>
<table class="tables_ui" id="t_draggable2"><h4>Table 2</h4>
<tbody class="t_sortable">
<tr>
<th>Title</th>
<th>Status</th>
<th>Creation date</th>
</tr>
<!-- More <td> rows here ... -->
</tbody>
</table>
<!-- More tables here ... -->
Javascript:
<script>
$(document).ready(function() {
var $tabs = $('#t_draggable2')
$("tbody.t_sortable").sortable({
connectWith: ".t_sortable",
items: "> tr:not(:first)",
appendTo: $tabs,
helper:"clone",
zIndex: 999990
}).disableSelection();
var $tab_items = $(".nav-tabs > li", $tabs).droppable({
accept: ".t_sortable tr",
hoverClass: "ui-state-hover",
drop: function( event, ui ) { return false; }
});
});
</script>
For an $.ajax call in js you should pay attention to a couple of things regarding what you'd like to pass to the PHP file and what you'd want as a return (response). A simple $.ajax call for posting data down below:
var Example1 = "123";
var Example2 = "456";
$.ajax({
type: "POST",
data: {
Example1: example1,
Example2: example2
},
url: "config/post.php",
success: function(){
setTimeout(function(){// wait for 5 secs(2)
location.reload(); // then reload the page.(3)
}, 100);
}
})
In the example above the variables (var), "Example1" and "Example2" will be inserted inside the request as the data.
Within your url: you'll specify the post url to your php file.
In the PHP file you're then able to obtain the data by using the second data { Attributes in a $_REQUEST see the example below:
$example1 = $_REQUEST['example1'];
$example2 = $_REQUEST['example2'];
echo $example1 . $example2;
To check if your data is obtained you could use the console.log() function above your $.ajax call to be sure.
var Example1 = "123";
var Example2 = "456";
// Check for the values
console.log(Example1 + Example2)
$.ajax({
type: "POST",
data: {
Example1: example1,
Example2: example2
},
url: "config/post.php",
success: function(){
setTimeout(function(){// wait for 5 secs(2)
location.reload(); // then reload the page.(3)
}, 100);
}
})
I hope this helps and if you have any questions please ask them in the comments section! (:

Highlight some rows of my table in javascript

I need to highlight some rows of my table. This highlight is based on the rows present in my response object. This object can be as follow:
<table id="ListRequests" class="table table-striped">
<tbody>
<tr id="13955">
<td>JEAN DUPONT</td>
<td>ACLIMEX SPRL</td>
</tr>
</tbody>
</table>
Here is my javascript code:
var id = $("tbody tr", response).attr('id');
var cols = $('#' + id + ' td');
cols.effect("highlight", {}, 30000);
This works fine only if my response object contains only 1 row. Now I need to be able to highlight more than 1 rows at a time. So for example with the response object below:
<table id="ListRequests" class="table table-striped">
<tbody>
<tr id="13955">
<td>JEAN DUPONT</td>
<td>ACLIMEX SPRL</td>
</tr>
<tr id="13954">
<td>MIKE GIVER</td>
<td>ARGO INTERNATIONAL CORP</td>
</tr>
</tbody>
</table>
Any idea how to adapt my javascript code for that purpose ?
If you really want to do it the way you are doing it, than you need to use each
var trs = $("tbody tr", response);
trs.each( function () {
var id = this.id,
cols = $('#' + id + ' td');
cols.effect("highlight", {}, 30000);
});
Better off returning a JSON object with ids to select.
attr returns a single value, regardless how many elements are matched by the proceeding selector.
If you want to map every selected element to an ID and return array, you need map:
var ids = $("tbody tr", response).map(function (i, e) { return $(e).attr('id'); });
Once you have your list of IDs, you can iterate over that list, and highlight the matching rows in the DOM:
ids.forEach(function (id) {
var cols = $('#' + id + ' td');
cols.effect("highlight", {}, 30000);
});
Here is a working snippet.
The idea is to scrap the ids from the response you get by looping the tr nodes, from these ids build a css selector for the nodes you are interested in, and finally highlight all them.
function highlight(response){
// retrieve the ids from the response
var ids = $(response).find("tbody tr").map(function(){
// `this` will be the trs one after the other.
// `map` will put all returned values in an array.
return this.getAttribute("id");
}).get();
// build the css selector
var selector = "#" + ids.join(",#");
// highlight the corresponding nodes
$(selector).effect("highlight", {}, 30000);
}
// Call highlight with your response example.
highlight('<table id="ListRequests" class="table table-striped"><tbody><tr id="13955"><td>JEAN DUPONT</td><td>ACLIMEX SPRL</td></tr><tr id="13954"><td>MIKE GIVER</td><td>ARGO INTERNATIONAL CORP</td></tr></tbody></table>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
<table id="ListRequests" class="table table-striped">
<tbody>
<tr id="13955">
<td>JEAN DUPONT</td>
<td>ACLIMEX SPRL</td>
</tr>
<tr id="13954">
<td>MIKE GIVER</td>
<td>ARGO INTERNATIONAL CORP</td>
</tr>
<tr id="1211">
<td>OTHER ONE</td>
<td>MUSN'T BE HIGHLIGHTED</td>
</tr>
</tbody>
</table>

Limit dynamically added columns to table

Please take a look at this fiddle example. I'm adding new columns using AJAX on click. Is there a way to count the columns of the table and limit the number of new columns to 6? Could anyone give me suggestions?
jQuery:
$(function () {
var ajaxfunction = function(){
$('.area').on("click","button", function(){
var source = $(this).data('feed');
$.ajax({
url: source,
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title,
year = item.year,
job = item.Job,
education = item.Education,
background = item.Background,
ingredient = item.Ingredient;
$('#header').after('<th>'+title+'</th>')
$('#ingredient').after('<td>'+ingredient+'</td>')
$('#year').after('<td>'+year+'</td>')
$('#background').after('<td>'+background+'</td>')
$('#education').after('<td>'+education+'</td>')
$('#job').after('<td>'+job+'</td>')
});
$('#toptable').stickyTableHeaders(); //Fixed Header Plugin
},
});
});
}
ajaxfunction();
});
HTML
<div class="area">
<button>Class B</button>
<button>Class C</button>
<button>Class D</button>
</div>
<table id="toptable">
<thead>
<tr>
<th id="header" style="visibility:hidden">-</th>
</tr>
</thead>
<tbody>
<tr>
<td id="ingredient">Ingredient</td>
</tr>
<tr>
<td id="year">Year</td>
</tr>
<tr>
<td id="background">Background</td>
</tr>
<tr>
<td id="education">Education</td>
</tr>
<tr>
<td id="job">Job</td>
</tr>
</tbody>
</table>
Get Column Count (If you start using colspans this will need to change to reflect that):
var colcount = $("#toptable").find("tr:first th").length; or
var colcount = $("tr:first th", "#toptable").length; or
var colcount = $("#toptable tr:first th").length;
Limit the number of columns (tested and working):
$('.area').on("click","button", function(){
var colspan = $("#toptable tr:first th").length;
alert("Current number of Columns = " + colspan);
if(colspan > 6)
{
alert("Too Many Columns");
return false;
}
var source = $(this).data('feed');
//the rest of your code
});
See this working Fiddle
NOTE: Because you are adding columns on an Ajax Success result, the column count is only true at the time of the click event. This means that the column count could be more once the Ajax Response arrives. You need to either cancel the request if there is an Ajax call in progress, or redesign so that you're not making so many HTTP calls (which is bad practice anyway, something like 68% of all performance improvements on the web are found in reducing HTTP calls.)

How to update DataTables DOM?

I am using Datatables for a review system, An user can grade each item by clicking on stars(1 to 5).
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered" id="tabela-disciplinas-preferencia">
<thead>
<tr>
<th>Semestre</th>
<th>Curso</th>
<th>Disciplina</th>
<th>Nível de Interesse</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Engenharia de Software</td>
<td>Redes</td>
<td>
<div class="rating" valor="0">
<span valor="5">☆</span><span valor="4">☆</span><span valor="3">☆</span><span valor="2">☆</span><span valor="1">☆</span>
</div>
</td>
</tr>
....
</tbody>
</table>
My JS
$(document).ready(function() {
$('#tabela-disciplinas-preferencia').dataTable( {
"sPaginationType": "bootstrap"
} );
});
However when an user click to grade one item, I change valor attribute in rating div but datatables doesn't update their values internally.
Click rating event
$(document).ready(function() {
$('div.rating span').click(function(){
starR= new StarRating( $(this).parent());
starR.changeValue($(this).attr('valor'));
//Get TR Element
aPos = oTable.fnGetPosition( $(this).parent().parent().get(0) );
aData = oTable.fnGetData( aPos[0] );
//Get rating div
rating = aData[3];
aData[3] = $(rating).attr('valor', $(this).attr('valor'));
// ????
oTable.fnUpdate(aData[3]);
});
});
How can I update datatables DOM? I already got data and changed value but how can I update back to oTable?
Changing values and inserting back to aData already update oTable
$('div.rating span').click(function(){
starR= new StarRating($(this).parent());
starR.changeValue($(this).attr('valor'));
//update oTable row data
aPos = oTable.fnGetPosition( $(this).parent().parent().get(0) );
aData = oTable.fnGetData( aPos[0] );
aData[3] = $(aData[3]).attr('valor', starR.getValue());
});
That's solution I have found and seems working pretty well.
I know it's been a minute, but a simple alternative.
$('div.rating span').click(function () {
//Invalidate Row after DOM manipulation
var parentRow = $(this).closest('tr');
$('#your-table').DataTable().row(parentRow).invalidate().draw();
}
You can invalidate row(s) or column(s) that have been changed and the table will update itself. This method will keep search criteria intact.

Jquery Datatables - Make whole row a link

This maybe simple, but cant seem to figure it out. Using jquery datatables how can I make each row clickable to just link to a normal page? So if someone moused over any of the row the whole row will hightlight and be clickable and link to whatever url I would want it to link to when clicked.
I've use the fnDrawCallback parameter of the jQuery Datatables plugin to make it work. Here is my solution :
fnDrawCallback: function () {
$('#datatable tbody tr').click(function () {
// get position of the selected row
var position = table.fnGetPosition(this)
// value of the first column (can be hidden)
var id = table.fnGetData(position)[0]
// redirect
document.location.href = '?q=node/6?id=' + id
})
}
Hope this will help.
This did it for me using the row callback.
fnRowCallback: function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
responsiveHelper.createExpandIcon(nRow);
$(nRow).click(function() {
document.location.href = 'www.google.com';
});
},
$('#myTable').on( 'click', 'tbody tr', function () {
window.location.href = $(this).data('href');
});
where #myTable is the ID of the table, and you need put the href in the tr, like that:
<tr data-href="page.php?id=1">
<th>Student ID</th>
<th>Fullname</th>
<th>Email</th>
<th>Phone</th>
<th>Active</th>
</tr>
It's simple enough to do this with a vanilla <table>, but I don't see why this wouldn't work with a jQuery DataTables one either.
$('#myTableId').on('click', 'tbody > tr > td', function ()
{
// 'this' refers to the current <td>, if you need information out of it
window.open('http://example.com');
});
You'll probably want some hover event handling there as well, to give users visual feedback before they click a row.
You can also use the DataTables plugins api which allows you to create custom renderers.
Very cool: JS addon here
And using the fnDrawCallback
fnDrawCallback: function() {
this.rowlink();
},
You can do that to make row clickable :
<script type="text/javascript">
var oTable;
$(document).ready(function() {
oTable = $('#myTable').dataTable({
"ajax" : "getTable.json",
"fnInitComplete": function ( oSettings ) {
//On click in row, redirect to page Product of ID
$(oTable.fnGetNodes()).click( function () {
var iPos = oTable.fnGetPosition( this );
var aData = oSettings.aoData[ iPos ]._aData;
//redirect
document.location.href = "product?id=" + aData.id;
} );
},
"columns" : [ {
"data" : "id"
}, {
"data" : "date"
}, {
"data" : "status"
}]
});
});
</script>
<table id="myTable" class="display" cellspacing="0" width="100%">
<thead>
<tr>
<th>#</th>
<th>Date</th>
<th>Status</th>
</tr>
</thead>
<tbody></tbody>
</table>
I think it will be like that
$('#invoice-table').dataTable({
"fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
var slug = $(nRow).data("slug");
$(nRow).attr("href", "/invoices/" + slug + "/");
$(nRow).css( 'cursor', 'pointer' );
$(nRow).click(function(){
window.location = $(this).attr('href');
return false;
});
}
});
And the table row like that
<tr class="invoice_row" data-slug="{{ invoice.slug }}">
<td>{{ invoice.ref }}</td>
<td>{{ invoice.campaign.name }}</td>
<td>{{ invoice.due_date|date:'d-m-Y' }}</td>
<td>{{ invoice.cost }}</td>
<td>
<span class="label label-danger">Suspended</span>
</td>
</tr>
This worked fine with me
**I have used a simple solution for this. Add onclick on tr and you are done. Tested with jquery datatable **
<tr onclick="link(<?php echo $id; ?>)">
function link(id){
location.href = '<?php echo $url ?>'+'/'+id;
}
Recently I had to deal with clicking a row in datatables.
$(document).ready(function() {
$("#datatable tbody tr").live( 'click',function() {
window.open('http://www.example.com');
} );
} );

Categories