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.
Related
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.
I found out how to delete a row with this jQuery code. While clicking on a td with the class delete and a garbage icon.
HTML
<table id="foo" class="display" cellspacing="0" width="100%">
<tbody>
<tr>
<td>Foo1</td>
<td>Foo2</td>
<td>Foo3</td>
<td class="delete">IMAGE src here</td>
<td><img src="http://placehold.it/20x20"></td>
</tr>
</tbody>
JAVASCRIPT
$('#foo tbody').on( 'click', 'tr .delete', function () {
$(this).closest('tr').fadeOut("slow", function(){
$(this).remove();
})
} );
But I did not find anything about duplicating rows. I just want to click on a td with another icon in it and the row is duplicated below.
To duplicate a row, you'll need to copy all of its data into an array, then call row.add() to insert this data as a new row.
Something like:
<table id="foo" class="display" cellspacing="0" width="100%">
<tbody>
<tr>
<td>Foo1</td>
<td>Foo2</td>
<td>Foo3</td>
<td class="delete">IMAGE src here</td>
<td class="copy">IMAGE src here</td>
<td><img src="http://placehold.it/20x20"></td>
</tr>
</tbody>
$('#foo tbody').on( 'click', 'tr .copy', function () {
var row_data = [];
$(this).closest('tr').find('td').each(function() {
row_data.push($(this).text());
});
// you'll need a reference to your DataTable here
table.row.add(row_data).draw();
});
To get a reference to your DataTable, assign the result of the DataTable() method to a var.
$(document).ready(function() {
var table = $('#foo).DataTable( { "paging": false, "info": false });
// set up your event handlers, etc.
});
If you append a row with jQuery instead of DataTables method like row.add(), you'll lose the row when you sort or page the table.
Here's the jQuery that adds a row duplicate right underneath it, where DataTables is concerned. It has a caveat that this method may not retain any sorting or filtering set by the user.
$('#formtable tbody').on( 'click', 'button.btn-success', function () {
//destroy instance of DataTables
table.destroy(false);
//script assumes button is clicked on the line that needs to be duplicated
var btn = this;
//copy and insert row right below the original
var line = $(btn).parents('tr');
line.after(line.clone());
//since clone retains only input field values, but not dropdown selections,
//each dropdown value must be assigned individually
line.next().find("select.shape").val(line.find("select.shape").val());
line.next().find("select.material").val(line.find("select.material").val());
line.next().find("select.supplied").val(line.find("select.supplied").val());
//re-creating DataTables instance
//notice that "table" has no "var" in front - that's because it is pre-defined.
table = $('#formtable').DataTable({
"columnDefs": [ {
"searchable": false,
"orderable": false,
"targets": "_all"
} ],
"paging": false,
"info": false,
"ordering": true,
"searching": false,
"rowReorder": true
});
//"Index Column" values re-calculation
table.column(0).nodes().each( function (cell, i) {
cell.innerHTML = i+1;
});
});
Hope this helps.
Try this:
HTML
<table id="foo" class="display" cellspacing="0" width="100%">
<tbody>
<tr>
<td>Foo1</td>
<td>Foo2</td>
<td>Foo3</td>
<td class="delete">IMAGE src here</td>
<td class="duplicate"><img src="http://placehold.it/20x20"></td>
</tr>
</tbody>
</table>
SCRIPT
$('#foo tbody').on( 'click', 'tr .delete', function () {
$(this).closest('tr').fadeOut("slow", function(){
$(this).remove();
})
} );
$('#foo tbody').on( 'click', 'tr .duplicate', function () {
var myTr = $(this).closest('tr');
var clone = myTr.clone();
myTr.after(clone);
} );
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>
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.)
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');
} );
} );