Datatable hide and show rows based on a button click event - javascript

So I have this datatable that is generated by php dynamically once. But once it's loaded, I don't want to reload the whole table since there's only a small javascript if statement that I am doing. When you press the button, I compare a data attribute that is on my tr. If it doesn't fit, I'd like to hide them, else, I'd like to show them. So here is what I tried so far.
HTML
<div style="margin: 30px 0;">
<button class="btn btn-primary" id="myClientButton">Voir mes clients seulements</button>
</div>
<table id="advancedSearchTable">
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th>Subject</th>
<th>Date</th>
<th>Profile</th>
</tr>
</thead>
<tbody>
{% for entity in entities %}
<tr data-user="{{ entity.user.id }}" class="values">
<td>{{ entity }}</td>
<td>{{ entity.mainphone }}</td>
<td>{{ entity.email }}</td>
<td>{{ entity.tagline }}</td>
<td>{{ entity.createdDate|date('d-m-Y') }}</td>
<td><span class="glyphicon glyphicon-eye-open"></span></td>
</tr>
{% endfor %}
</tbody>
</table>
The Loop is made in Symfony 2 (Using Twig Template, if you don't understand it it doesn't really matter) all you have to understand is that the attribute on "data-user" is created by PHP and that every entry of my database is going in this loop.
Then, in jQuery I have this:
<script>
$('#advancedSearchTable').DataTable(
{
"language": {
"url": "//cdn.datatables.net/plug- ins/9dcbecd42ad/i18n/French.json"
},
responsive: true
});
$('#myClientButton').on('click', function(){
if ($(this).hasClass('active')){
$(this).removeClass('active');
$('tr.values').show();
}
else{
$(this).addClass('active');
$('tr.values').each(function(){
if ($(this).attr('data-user') != 5){
$(this).hide();
}
});
}
});
</script>
It works very well. The only problem is that the DataTable then is not "replacing itself". So, for example, if it has 25 pages, it keeps 25 pages and when you press on the "next table page" button, it refreshes the "table page" and things are not hidden anymore. I searched alot but I couldn't find a way. I really don't want to use ajax for this, since it only need to be filled once with value and then it will only have to hide or show depending on the button being active or not... Is it even possible using this jQuery plugin ?
Thanks in advance.

Yes, it is indeed possible, but you will need a different approach. Hiding rows with jQuery and not through dataTables itself is generally a bad idea, since dataTables is not aware of changes made to the original <table> element in DOM. There is no "somewhere-in-code-another-script-has-hidden-a-row"-event dataTables can hook into. That is why dataTables seems to "forget" changes, it is simply not aware of those changes, and the dataTables internals stay untouched.
So use a custom filter instead. The following small piece of code does what you want - hiding all rows having a data-user attribute different than 5. It works across sorting and pagination. The last piece of code is an example of a reset-button.
$("#hide").click(function() {
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
return $(table.row(dataIndex).node()).attr('data-user') == 5;
}
);
table.draw();
});
$("#reset").click(function() {
$.fn.dataTable.ext.search.pop();
table.draw();
});
demo -> http://jsfiddle.net/d5hre2ux/

According to this https://datatables.net/examples/plug-ins/range_filtering.html it is possible to use data parameter to filter by any value shown on the table.
$("button").click(function() {
$.fn.dataTable.ext.search.push(
function(settings, data, dataIndex) {
return data[3] != "63";
}
);
table.draw();
});

Related

Vue js and Data Table Panigation not Working

Ok, so unfortunately I have come across this issue. So first a little about specs of my app.
I am using
Vue.js
vue-resource.js
jQuery
jQuery DataTables
Now because I'm grabbing the data through vue-resource, for some reason when the ajax call is final finished and vue imports the data to the table, datatables decides not to render pagination, and displays all 200 results on one page. Is there anyway to refresh datatables so it is rendered with pagination after it has been imported into the table?
My ajax call:
this.$http.get('getDispachedEmails', function(data){
console.log(data['orders']);
this.customers.push(data['orders']);
var dt = $('#myTable').DataTable();
});
My Table:
<table id="myTable" class="u-full-width">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Sex</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr v-repeat="customers[0]">
<td>#{{ firstName }} #{{ lastName }}</td>
<td>#{{ email }}</td>
<td>#{{ trackingNumber }}</td>
<td>#{{ address }}</td>
</tr>
</tbody>
</table>
EDIT
I have found out that none of the functions work. If i try to select any row, the table is instantly cleaned. My model (vue model) still has all the objects inside.
SOLUTION:
I just set a wait time to initiate data tables after I collect the data via ajax request. It's a little ghetto, but a least it works. If I find a better fix Ill edit this post.
this.$http.get('getDispachedEmails', function(data){
console.log(data['orders']);
this.customers.push(data['orders']);
setTimeout(function(){$('#myTable').DataTable();}, 5000);
});
A delay of 0 did the trick for me, although not sure why.
setTimeout(function(){$('#myTable').DataTable();}, 0);
I've built a dedicated vue grid component: vue-tables . You might want to check it out.

WTForms submitting form twice when multiple forms are in the same page

On my view I have a few different forms. In one you enter a first and last name to search for. If there are results, the page refreshes and a second form to pick a user is displayed as a table where clicking on a row submits the data from that row. For some reason, submitting the second form results in submitting two values for each field: one completely empty and one with the correct information.
I have some javascript that will be executed when a row in a table is clicked. It's supposed to fill out and submit a hidden form with the data from the table. The problem I'm running into is that when the form is submitted, two sets of values are submitted. request.form after the form is submitted contains the following:
ImmutableMultiDict([('csrf_token', u'1420171907##6ad5346730985191250a52e6432e924ef05c23ee'), ('last_name', u''), ('last_name', u'Smith'), ('first_name', u''), ('first_name', u'John')])
Here's the script:
$('table#theTable tr').click(function () {
var cells = this.getElementsByTagName('td');
$('#selectuser_last_name').val(cells[0].innerHTML);
$('#selectuser_first_name').val(cells[1].innerHTML);
document.selectuser.submit();
});
and here is the HTML to go along with it:
<table id="theTable">
<thead>
<tr>
<th>Last</th>
<th>First</th>
</tr>
</thead>
<tbody>
{% for user in users %}
<tr>
<td>{{ user.last_name }}</td>
<td>{{ user.first_name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<form id=selectUserForm action="/handle_users" method="post" name="selectuser">
{{ forms.selectuser.hidden_tag() }}
{{ forms.selectuser.last_name(id="selectuser_last_name") }}
{{ forms.selectuser.first_name(id="selectuser_first_name") }}
<input type="submit">Test</input>
</form>
I'm using Python and Flask to handle whatever is posted.
It seems you're actually submitting twice- once before there's anything in the form, and once after it's populated (the latter by the javascript, the former via the form submit mechanism).
If the user isn't really inputting anything into the form, but this is a simple call to the server any time a row is clicked. Skip the whole form, it's not helping here. Just pass a call to the server with the info you need- can be a simple ajax post:
$('table#theTable tr').click(function () {
var cells = this.getElementsByTagName('td');
$.ajax({
type : "POST",
url : "/handle_users",
async:true,
contentType : 'application/json;charset=UTF-8',
data: JSON.stringify({first_name:cells[0].innerHTML,last_name:cells[1].innerHTML}, null, '\t'),
success : function(data) {
// optional: do something when server-side processing is done
}
});
});
Then Grab your data on from flask using request.get_json() in the /handle_users route.

removing inner table filter bootstrap

I have a filterable table containing a collapsible list in a column. The collapsible contains another table. Sample of the situation.
The problem is that when anything is written to filter only the required items, the inner table also gets filtered. Is there a way to avoid this.
Suggestions about how else to display something like this are also welcome.
If you want to filter only from the Name column, you can try to use below code:
$('#filter').keyup(function () {
var stringValue = $(this).val();
$("#outer-table tr.row").each( function( index ) {
$(this).hide();
$(this).find(".panel-title a:contains("+stringValue+")").parents("tr").show();
});
});
EDIT: I have tested the new code above, it works as expected.
HTML changes, easier to get ONLY every <tr> that are part of your outer-table:
Change your outer-table tag from <tbody class="searchable">, into this, <tbody id="outer-table" class="searchable">
Then add a selector to every <tr> inside outer-table but NOT inside inner-table, like this:
</tr>
<tr class="row">
<td><div id="collapsibleMain2" class="panel-group">
</tr>
<!-- and so on -->
For more info about the jQuery functions that I used above:
contains
each
hide

How to show a table on click of a button in php?

I want to list files from mysql table to a webpage in php. For this i use tables so that i have more regular view. Now there are n numbers of tables on a page. This n is depending upon a mysql query. I am able to list the files on the page. But if numbers of rows in table get increased and value of n is also get increased then my page length will be very long. So i want to give a tree view to each table. Like there will be a button over each table with value '+'. when i click on it the value get change to '-' and that table should be visible.
Here what i tried
<script type="text/javascript">
$(document).ready(function(){
$(".show").html("<input type='checkbox'>");
$('.tree td').hide();
$('th ').click( function() {
$(this).parents('table').find('td').toggle();
});
});
<table width="100%" class="tree">
<tr width="20px"><th colspan="2" class="show"> </th></tr>
<tr>
<td width="50%"><b>Name</b></td>
<td width="50%"><b>Last Updated</b></td>
</tr>
while($row = $result_sql->fetch_assoc())
{
<tr>
<td width='50%'><a href='http://127.0.0.1/wordpress/?page_id=464&name_file={$row['name']}&cat={$cat}&sec={$sec}' target='_blank'>{$row['title']}</a></td>
<td width='50%'>{$row['created']}</td>
</tr>
}
</table>
This is not exact code.
as you can see i am able to do it but i am using a chackbox. i want to have a button with value + or - . There is one problem with this code. The line in which checkbox is showing if i click on it the table is expanded means it taking the entire row not only the checkbox. So anybody can help me with this?
Thanks
I know that this is a code sample, in the future try to provide a jsFiddle to make it easier for people to help. If you want to use +/-, you can make a minor modification like my example
<th colspan="2" width="100%"><span class="show"></span></th>
I basically added the show class to a span within the <th> and attached a click handler on it as well. When you click on it, it will toggle the <td> within the parent <table>... in addition, it will check the text-value in the <th> and inverse it
$('.show').click(function () {
$(this).parents('table').find('td').toggle();
$(this).text() == '+' ? $(this).text('-') : $(this).text('+');
});
Since you don't need a checkbox and you are using a <span>, it won't wrap across the entire <th>. Was this what you were looking for?
Get solution
<script type="text/javascript">
$(document).ready(function(){
$(".show").html("<input type='button' value='+' class='treebtn'>");
$('.tree td').hide();
$('.treebtn ').click( function() {
$(this).parents('table').find('th').parents('table').find('td').toggle();
if (this.value=="+") this.value = "-";
else this.value = "+";
});
});
It is working fine the way i wanted.

Generate delete confirmation box

In my application results are displaying as a table format.
Part of my code is,
{% for device in devices %}
<tr>
<td>{{ device.operator}}</td>
<td>{{ device.state }}</td>
<td>{{ device.tstampgps }}</td>
<td><button id='rec_delete'>Delete</button></td>
</tr>
{% endfor %}
Even if we press the delete button, I need to delete the particular record from the database. before that I want to prompt a confirmation box for that.
Can anyone help me?
Add a unique record Identifier that you can associate to DB to the button. Once confirmed you send this identifier to server with AJAX and sever code does the DB delete. Also change ID to class on repeating elements since ID's must be unique
HTML
<tr>
<td>{{ device.operator}}</td>
<td>{{ device.state }}</td>
<td>{{ device.tstampgps }}</td>
<td><button class='rec_delete' data-record_id="{{ device.DB_ID }}">Delete</button></td>
</tr>
JS
$('button.rec_delete').click(function(){
/* data() method reads the html5 data attribute from html */
var record_id=$(this).data('record_id');
if( confirm( 'Are you sure') ){
$.post( 'serverPage.php', { id: record_id}, function(){
/* code to run on ajax success*/
$(this).closest('tr').remove();
})
}
})
Server will receive the post key id as you would with any other form element name
Since I don't know Django, this doesn't include the delete part, which I assume you will AJAXify that (do an asynchronous request to delete). I'm also showing the $devices and $deletes variables as local variables here separately, more or less so you can see how you can store references and then work from those references (which I believe is a better practice than reselecting over and over).
Note also the use of:
jQuery(document).ready(function r($){
I'm using jQuery() in the global scope, which in a larger app you should always do to keep from conflicting with other libraries/frameworks which may use $(). This is also a best practice, and you can use $() within that anonymous function (closure). It's best to get used to doing it this way, IMO.
<table>
<thead>
<tr>
<th>Operator</th>
<th>State</th>
<th>T-Stamp GPS</th>
<th> </th>
</tr>
</thead>
<tbody>
<tr class="device">
<td>Verizon</td>
<td>OK</td>
<td>033830928</td>
<td>
<button type="button" id="d001" class="delete">Delete</button>
</td>
</tr>
...
</tbody>
</table>
NOTE
I made a slight but important change, with reference to the $self, since the AJAX will run the success handler after this is out of scope:
jQuery(document).ready(function r($){
var $devices = $('tr.device'),
$deletes = $devices.find('button.delete');
$deletes.click(function d(){
var $self = $(this).parents('tr.device'),
del = confirm('Delete device?');
if (del) {
// Do $.ajax() request, maybe using the
// clicked button's ID. Or you could put
// the row to delete ID on the TR element.
// And then on success of the AJAX, run:
$self.fadeOut(500, function f(){
$self.remove();
});
}
});
});​
http://jsfiddle.net/wMqr8/2
You can add a click event to your JavaScript, and if the user chooses the "ok" button, you can send a request to the view that takes care of removing the record or whatever
Try this:
<button id='rec_delete' onclick="return confirm('Are you sure?')">Delete</button>

Categories