After fiddling with my table layout I give up, I am looking for up to date and elegant way to sort this table layout with such numbers.
I tried this popular solution.
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
"formatted_numbers-pre": function ( a ) {
a = (a===" ") ? 0 : a.replace( /[^\d\-\.]/g, "" );
return parseFloat( a );
},
"formatted_numbers-asc": function ( a, b ) {
return a - b;
},
"formatted_numbers-desc": function ( a, b ) {
return b - a;
}
});
jQuery(document).ready(function() {
jQuery('#mieszkaniaList').DataTable({
responsive: true,
"columnDefs": [
{ "type": "formatted_numbers", "targets": '_all'},
],
"language": {
"decimal": ",",
"thousands": " ",
"lengthMenu": "Pokaż _MENU_ mieszkań na stronę",
"zeroRecords": "Niestety dla tego zakresu nie znaleźliśmy pasujących mieszkań ...",
"info": "Strona _PAGE_ z _PAGES_",
"infoEmpty": "Niestety brak mieszkań...",
"processing": "Przygotowujemy mieszkania...",
"search": "Szukaj",
"paginate": {
"first": "Pierwsza",
"last": "Ostatnia",
"next": "Następna",
"previous": "Poprzednia"
},
"infoFiltered": "(z _MAX_ mieszkań)"
}
});
});
Nr
Area
level
nr2
Price
Price per m2
01A
10 m2
1
1
502 200 PLN
7 200 PLN za m2
02A
20 m2
2
2
1 502 200 PLN
10 200 PLN za m2
03A
90 m2
3
3
2 502 200 PLN
15 200 PLN za m2
04A
120 m2
4
4
202 200 PLN
5 200 PLN za m2
Your approach looks close to me, but I can suggest some changes:
In your case you only need the -pre function - you do not need the -asc and -desc functions. In fact there is a note in the documentation which states that you cannot combine usage of -pre with the other two functions:
Note that in DataTables 1.10 a pre-formatter cannot be used with custom -asc and -desc methods - to use custom ordering functions you cannot apply a pre-formatter. This limitation will be addressed in the next major version of DataTables.
If you use -pre to convert your numbers-plus-text to numbers-only values, then sorting will use the numbers-only values automatically - and the data will automatically be handled as numeric, not text.
You need to handle the fact that some of your data contains strings with numbers ("m2"). A very simple way to handle these is to replace all occurrences of m2 with nothing, before performing the regex replacement.
Here is a runnable demo:
$(document).ready(function() {
$.fn.dataTable.ext.type.order['formatted_numbers-pre'] = function ( a ) {
a = a.replaceAll("m2", "");
a = (a===" ") ? 0 : a.replace( /[^\d\-\.]/g, "" );
console.log( a ); // for debugging only
return parseFloat( a );
};
var table = $('#example').DataTable( {
"columnDefs": [
{ "type": "formatted_numbers", "targets": '_all'},
]
} );
} );
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo</title>
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
<link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>
<body>
<div style="margin: 20px;">
<table id="example" class="display dataTable cell-border" style="width:100%">
<thead>
<tr>
<th>Nr</th>
<th>Area</th>
<th>Level</th>
<th>nr2</th>
<th>Price</th>
<th>Price per m2</th>
</tr>
</thead>
<tbody>
<tr>
<td>01A</td>
<td>10 m2</td>
<td>1</td>
<td>1</td>
<td>502 200 PLN</td>
<td>7 200 PLN za m2</td>
</tr>
<tr>
<td>02A</td>
<td>20 m2</td>
<td>2</td>
<td>2</td>
<td>1 502 200 PLN</td>
<td>10 200 PLN za m2</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
There is a logging statement in the above code, so you can see what data the -pre function is generating.
Related
I have this table with ng-repeat. All I want is to display one the value only once inside the ng-repeat.
My ng-repeat in tr
<tr ng-repeat="xx in results " >
<tr>{{xx.id}}</tr>
<tr>{{xx.invoicenumber}}</tr>
</tr>
Here's my table
ID
INVOICE#
1
112
1
113
1
114
2
115
2
116
Desired Output
ID
INVOICE#
1
112
113
114
2
115
116
#SprakenDude , Can you also share us the details about how and what is the structure of data you are receiving?
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<table>
<tr>
<td>Id</td>
<td>Invoice Number</td>
</tr>
<tr ng-repeat="xx in results " >
<td>{{printXXId(xx.id)}}</td>
<td>{{xx.invoicenumber}}</td>
</tr>
</table>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.preid=-1;
$scope.printXXId=function(id){
return $scope.preid==id?'':$scope.preid=id;
}
$scope.results=[
{
id:1,
invoicenumber:112
},
{
id:1,
invoicenumber:113
},
{
id:1,
invoicenumber:114
},
{
id:2,
invoicenumber:115
},
{
id:2,
invoicenumber:116
},
]
});
</script>
</body>
</html>
i'm learning spring boot with datatables. and now im success show data from MySQL to jquery datatables. and now im create CRUD, but my problem on this learning is delete data.
i'm understand with only table bootstrap create CRUD without datatables :
<table class="table table-striped">
<tr>
<th>Id</th>
<th>Product Id</th>
<th>Name</th>
<th>Price</th>
<th>Delete</th>
</tr>
<tr th:each="product : ${products}">
<td th:text="${product.id}">Id</td>
<td th:text="${product.productId}">Product Id</td>
<td th:text="${product.name}">descirption</td>
<td th:text="${product.price}">price</td>
<td><a th:href="${'/product/delete/' + product.id}">Delete</a></td>
</tr>
</table>
easy only declare local variable thymeleaf on my html.
how delete data from datatables with confirmation dialog ?
this my code datatables :
$(document).ready (function() {
var table = $('#productsTable').DataTable({
"sAjaxSource": "/api/products",
"sAjaxDataProp": "",
"order": [[ 0, "asc" ]],
"columns": [
{ "mData": "id"},
{ "mData": "name" },
{ "mData": "price" },
{ "mData": "productId" },
{ "mData": "version" },
{
data: null,
defaultContent: 'Delete',
orderable: false
}
]
});
$('#btnDelete').on( 'click', 'a.remove', function (e) {
e.preventDefault();
editor.remove( $(this).closest('tr'), {
title: 'Delete Product',
message: 'Are you sure you wish to delete this data ?',
buttons: 'Delete'
} );
} );
});
products.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<title>Latihan Spring Boot</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.15/js/jquery.dataTables.min.js"></script>
<script src="/js/product.js"></script>
<link rel="stylesheet" href=
"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.15/css/jquery.dataTables.min.css">
</head>
<body>
<div class="container">
<h1 align="center">Products Table</h1>
<p><a class="btn btn-primary">Add Product</a></p>
<table id="productsTable" class="display">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
<th>Product ID</th>
<th>Version</th>
<th></th>
</tr>
</thead>
</table>
</div>
</body>
</html>
Try using jQuery confirm().
Update your code like so
$('#btnDelete').on( 'click', 'a.remove', function (e) {
e.preventDefault();
if(!confirm("Sure you want to delete!")){
return false;
}
editor.remove( $(this).closest('tr'), {
title: 'Delete Product',
message: 'Are you sure you wish to delete this data ?',
buttons: 'Delete'
} );
} );
});
In vue.js how can you filter a table using mutiple filters that target a specific column on the table.
For example if I have two search fields name and age how can I bind them to search the respective columns on the table below. So if user enters a name in the name input it should only search for a name on the name column. If the user enters an age as well then it should form an and condition and search for an age in the age column. Currently the filters simply search the entire table.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The Vast World of Vue.js</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
</head>
<body id="demo" class="container">
<input v-model="name" class="form-control" placeholder="search by name"><br>
<input v-model="age" class="form-control" placeholder="search by age">
<table class="table table-striped">
<thead>
<tr>
<th >
Name
</th>
<th >
Age
</th>
</thead>
<tbody>
<tr v-for="item in people | filterBy name | filterBy age">
<td>{{ item.name }}</td>
<td>{{ item.age }}</td>
</tr>
</tbody>
</table>
<script src="http://vuejs.org/js/vue.js"></script>
<script>
new Vue({
el: '#demo',
name: '',
age: '',
data: {
people: [
{ name: 'John', age: 50 },
{ name: 'Jane', age: 22 },
{ name: 'Paul', age: 34 },
{ name: 'Kate', age: 15 },
]
}
});
</script>
</body>
</html>
Vue 2
Since we don't have filters anymore, you'd need to use a computed property.
So you can do something like:
{
data: {
people: [{ name: }],
age: 28,
name: 'bi',
}
computed: {
filteredPeople () {
const { name, age, people } = this
return this.people
.filter(person => person.name.toLowerCase().indexOf(name.toLowerCase()) > -1)
.filter(person => person.age === age)
},
},
}
Then you'd loop through filteredPeople instead of people
<tr v-for="person in filteredPeople">...</tr>
Vue 1
If you take a look at the second example in API documentation for filterBy you'll see the ability to limit it to a field.
You'd want something like:
item in people | filterBy name in 'name' | filterBy age in 'age'
Recently, I got a requirement for an implementation of adding Child rows in a table. I have gone through the few APIs and found that datatables fits into my requirement. As of now I am implementing this web application in Springs and getting the data from the controller.
That is $resultSet.
Now this dynamic data I have to render in jsp page. Here I got stucked because I am not able to implement with datatable. I have seen the example of http://datatables.net/examples/api/row_details.html and tried removing Ajax data and used c:foreach loop in place it. But i didn't get any luck.
So can you guys please tell me how do I use datatables with the dyncamic data in order to display child rows.
My main concern is:
$(document).ready(function() {
var table = $('#example').DataTable( {
"ajax": "../ajax/data/objects.txt",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" }
],
"order": [[1, 'asc']]
} );
How do I represent the above block.
I tried with <table id="xx"> <c:foreach loop to iterate>
You can use data option to feed data into DataTables directly instead of using server-side script to return data via Ajax. This initialization option can be useful when creating a table from a JavaScript data source, or from a custom Ajax data get. However the data has to be of type Array.
I'm not familiar with Spring framework but I'm assuming you can produce a string with data in JSON format and output it in your page to assign to table_data_json. I'm using a sample JSON string var table_data_json = '[ /* skipped */ ]';.
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
'<tr>'+
'<td>Full name:</td>'+
'<td>'+d.name+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extension number:</td>'+
'<td>'+d.extn+'</td>'+
'</tr>'+
'<tr>'+
'<td>Extra info:</td>'+
'<td>And any further details here (images etc)...</td>'+
'</tr>'+
'</table>';
}
$(document).ready(function() {
var table_data_json = '[{"name":"Tiger Nixon","position":"System Architect","salary":"$320,800","start_date":"2011/04/25","office":"Edinburgh","extn":"5421"},{"name":"Garrett Winters","position":"Accountant","salary":"$170,750","start_date":"2011/07/25","office":"Tokyo","extn":"8422"},{"name":"Ashton Cox","position":"Junior Technical Author","salary":"$86,000","start_date":"2009/01/12","office":"San Francisco","extn":"1562"}]';
var table = $('#example').DataTable( {
"data": JSON.parse(table_data_json),
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{ "data": "name" },
{ "data": "position" },
{ "data": "office" },
{ "data": "salary" }
],
"order": [[1, 'asc']]
} );
// 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');
}
} );
} );
td.details-control {
background: url('https://raw.githubusercontent.com/DataTables/DataTables/1.10.7/examples/resources/details_open.png') no-repeat center center;
cursor: pointer;
}
tr.shown td.details-control {
background: url('https://raw.githubusercontent.com/DataTables/DataTables/1.10.7/examples/resources/details_close.png') no-repeat center center;
}
<link href="//cdn.datatables.net/1.10.7/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>
<table id="example" class="display">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</tfoot>
</table>
If I misunderstood your question, please let me know and I will update my answer.
With jQuery delivered by Google CDN and DataTables delivered by Microsoft CDN I have the following page, where 3 checkboxes allow toggling good, bad, neutral comments about some user (here fullscreen):
My problem is:
With DataTables 1.9.2 this works well: here jsFiddle
With DataTables 1.9.4 this does not work: here jsFiddle and a copy of my simple test case is at the bottom of this question.
The problematic code is probably here:
$.fn.dataTableExt.afnFiltering.push(
function(oSettings, aData, iDataIndex) {
if ('comments_table' == oSettings.nTable.id) {
//console.dir(oSettings);
console.dir(aData);
var nice = aData[3];
if (nice == true)
return $('#good_box').is(':checked');
if (nice == false)
return $('#bad_box').is(':checked');
return $('#neutral_box').is(':checked');
}
return true;
}
);
The console.dir(aData); prints for dataTables 1.9.2 a 4-elements array and I can grab its last element (shown by the red arrow in the above screenshot).
But for DataTables 1.9.4 it only prints a 1-element array for some reason. Why?
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables_themeroller.css">
<link type="text/css" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/redmond/jquery-ui.css">
<style type="text/css">
a img.good {
border: 3px solid #009900;
}
a img.bad {
border: 3px solid #FF3333;
}
a img.neutral {
border: 3px solid #9999FF;
}
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js"></script>
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
<script type="text/javascript">
var ME = "http://gravatar.com/avatar/55b3816622d935e50098bb44c17663bc.png";
$(function() {
$.fn.dataTableExt.afnFiltering.push(
function(oSettings, aData, iDataIndex) {
if ('comments_table' == oSettings.nTable.id) {
//console.dir(oSettings);
console.dir(aData);
var nice = aData[3];
if (nice == true)
return $('#good_box').is(':checked');
if (nice == false)
return $('#bad_box').is(':checked');
return $('#neutral_box').is(':checked');
}
return true;
}
);
$('#good_box,#bad_box,#neutral_box').click(function() {
commentsTable.fnDraw();
});
var commentsTable = $('#comments_table').dataTable({
bJQueryUI: true,
sPaginationType: 'full_numbers',
bProcessing: true,
bDeferRender: true,
aaData: [
{"day":"17.02.2014","about":"A neutral comment about this user","nice":null,"female":false,"author":"OK250354887500","rep_id":960962,"avatar":ME},{"day":"30.11.2013","about":"A positive comment about this user","nice":true,"female":false,"author":"DE10859","avatar":ME},{"day":"23.11.2013","about":"A positive comment about this user","nice":true,"female":false,"author":"OK100836631753","avatar":ME},{"day":"01.04.2013","about":"A positive comment about this user","nice":true,"female":false,"author":"DE8547","avatar":ME},{"day":"29.03.2013","about":"A NEGATIVE comment about this user","nice":false,"female":false,"author":"OK462728443459","rep_id":734122,"avatar":ME},{"day":"26.03.2013","about":"A positive comment about this user","nice":true,"female":true,"author":"DE10472","avatar":ME},{"day":"24.03.2013","about":"A positive comment about this user","nice":true,"female":true,"author":"DE9454","avatar":ME},{"day":"22.03.2013","about":"A NEGATIVE comment about this user","nice":false,"female":false,"author":"DE6294","rep_id":727815,"avatar":ME},{"day":"04.02.2013","about":"A neutral comment about this user","nice":null,"female":false,"author":"VK119456690","rep_id":683816,"avatar":ME}
],
fnInitComplete: function () { this.fnAdjustColumnSizing(); },
aaSorting: [[0, 'desc']],
aoColumns: [
/* 0: day */ { mDataProp: 'day', bSearchable: false, bSortable: true, bVisible: true },
/* 1: about */ { mDataProp: 'about', bSearchable: true, bSortable: false, fnRender: renderAbout },
/* 2: avatar */ { mDataProp: 'avatar', bSearchable: false, bSortable: false, fnRender: renderAvatar },
/* 4: nice */ { mDataProp: 'nice', bSearchable: false, bSortable: false, bVisible: false }
]
});
});
function renderAbout(obj) {
var about = obj.aData['about'];
var rep_id = obj.aData['rep_id'];
if (rep_id) {
return '<i>«' + about + '»</i> delete';
}
return '<i>«' + about + '»</i>';
}
function renderAvatar(obj) {
var avatar = obj.aData['avatar'];
var author = obj.aData['author'];
var nice = obj.aData['nice'];
if (author) {
var cls = 'neutral';
if (nice == true)
cls = 'good';
else if (nice == false)
cls = 'bad';
return '<img class="' + cls + '" height="45" src="' + avatar + '">';
}
return '<img height="45" src="' + avatar + '">';
}
</script>
</head>
<body>
<p>Show:
<label><input type="checkbox" id="good_box" checked>good</label>
<label><input type="checkbox" id="bad_box" checked>bad</label>
<label><input type="checkbox" id="neutral_box" checked>neutral</label>
comments:</p>
<table id="comments_table">
<thead>
<tr>
<th>Date</th>
<th>Comment</th>
<th>Author</th>
<th>Rating</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</body>
</html>
I have posted this question at the DataTables forum as well.
The workaround for now is to make the 4th (nice) column searchable too and use the code
var nice = aData[1];
Here is the jsFiddle, which works with 1.9.4