how to add multiple column sum total in datatable - datatable

I have issue in showing sum total of some columns in data table. One issue is my table is dynamically created i.e user select columns to show so that column index are not fixed!
Secondly footerCallback on adding code throws ncaught TypeError: Cannot read property 'nTf' of undefined error
<tfoot>
<tr>
<td colspan='2'> <span style="float:right;"id ='totalcol1'></span> </td>
</tr>
</tfoot>
FooterCAllback is defined inside var table=('#mytable').Datatable()
"footerCallback": function ( row, data, start, end, display ) {
var api = this.api(), data;
$(api.column(11).footer()).html(
api.column(11).data().reduce( function ( a, b ) { return a + b;})
);
/* For second column
$(api.column(12).footer()).append(
api.column(12).data().reduce( function ( a, b ) { return a + b;})
);*/
},

I found an example that looks like exactly what you want to do
$(document).ready(function() {
$('#example').DataTable( {
"footerCallback": function ( row, data, start, end, display ) {
var api = this.api(), data;
// Remove the formatting to get integer data for summation
var intVal = function ( i ) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '')*1 :
typeof i === 'number' ?
i : 0;
};
// Total over all pages
total = api
.column( 4 )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
// Total over this page
pageTotal = api
.column( 4, { page: 'current'} )
.data()
.reduce( function (a, b) {
return intVal(a) + intVal(b);
}, 0 );
// Update footer
$( api.column( 4 ).footer() ).html(
'$'+pageTotal +' ( $'+ total +' total)'
);
}
} );
} );

Related

React Material UI table update all rows height according to largest height of cell

Goal: I need to update the height of all rows according to the tallest cell between two tables.
I have created two tables that exist side by side that both look like so:
<Table aria-label="simple table">
<TableHead>
<TableRow>
{actualColumn.length && actualColumn.map(col => (
<TableCell>{col.feature.label}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{
rows.length && rows.map((cells, i) => (<TableRow sx={{
'&:nth-of-type(odd)': { backgroundColor: '#F8FBFE', },
'&:nth-of-type(even)': { backgroundColor: '#ECF1F6', },
}} key={i}>
{cells.map((cell) => {
const value = getCellValue(cell);
return (
<TableCell ref={cellRef} >
{value !== "" && <div>{value}</div>}
</TableCell>
)
})}
</TableRow>))
}
</TableBody>
</Table>
I tried to pass in as you can see a cellRef to access the the specific cell, and then inside useCallback to update the style of the cell height.
const [rowHeight, setRowHeight] = useState(0);
const rowRef = useCallback(node => {
if (node !== null) {
const rh = node.offsetHeight;
if (rowHeight < rh) {
setRowHeight(rh);
}
node.style.height = `${rowHeight}px`;
}
}, []);
Is there a different approach that i should be taking? Clearly this is not working but perhaps im on the right path.
The answer seems to have been easier than i thought.
I set the rowHeight as part of the state, and then used that to give height to both of the tables body. Then i also added a ref on the table body itself, and styled each row with height: 'inherit'
Code looks like so:
const [rowHeight, setRowHeight] = useState(0);
const rowRef = useCallback(node => {
if (node !== null) {
[...node.childNodes].forEach(({ offsetHeight = 0 }) => {
if(rowHeight < offsetHeight) {
setRowHeight(() => offsetHeight)
}
})
}
}, [rowHeight]);

VueJS: how can i use two computed properties inside one v-for?

I have this computed property:
computed: {
filteredCars: function() {
var self = this
return self.carros.filter(function(carro) {
return carro.nome.indexOf(self.busca) !== -1
})
},
},
and i'm using v-for like this:
<tr v-for="carro in filteredCars">
<td>{{carro.nome}}</td>
<td>{{carro.marca}}</td>
<td>{{carro.categoria}}</td>
<td>{{carro.motor}}</td>
<td>{{carro.cambio}}</td>
<td>{{carro.preco}}</td>
</tr>
but I need to create another computed property to limit my data quantity, how i call it inside the same v-for?
I'm trying to use filteredCars + another filter, in this case something like 'limit' filter from vue 1.x. I've done an example using Vue 1.x but i need to do using Vue 2.x.
Vue.filter('limit', function (value, amount) {
return value.filter(function(val, index, arr){
return index < amount;
});
<tr v-for="carro in carros | limit upperLimit>
...
</tr>
Just use Array.prototype.slice (Array.prototype.splice should work too) in the computed property.
data: {
carros: [...],
upperLimit: 30
},
computed: {
filteredCars: function() {
const arr = this.carros.filter(function(carro) {
return carro.nome.indexOf(self.busca) !== -1
});
if (arr.length > this.upperLimit) {
return arr.slice(0, this.upperLimit + 1);
}
return arr;
},
}

Sorting columns using asc/desc and default ordering

I have multiple columns in my table, for example:
id | name | amount | description
And I want to sort each column - on the first click in ascending order, on the second on descending order, on the third go back to default, and all over again.
The default is the id column sorded in asc order.
So, the default state in the reducer is:
sort: {
key: 'id',
desc: false
}
The next steps on clicking name column would be:
sort: {
key: 'name',
desc: false
}
sort: {
key: 'name',
desc: true
}
sort: {
key: 'id',
desc: false
}
The view calls an action using column's name as a parameter:
<td onClick={() => this.props.sort('name')}>Name</td>
<td onClick={() => this.props.sort('amount')}>Amount</td>
An action should dispatch such key and desc values so that it matches my pattern:
export function sort(key) {
return dispatch => {
};
};
How can I do this?
Here you go, brief explanation in code sample.
I setup 2 columns only, cause I am lazy, sorry.
Fiddle: https://jsfiddle.net/u1wru0gb/1/
const data = [
{ id: 1, name: 'Bruce' },
{ id: 3, name: 'Martin' },
{ id: 2, name: 'Andrew' },
];
/**
* Nothing interesting, just render...
*/
function Table({ data, sortByKey }) {
const renderRow = ({ id, name }, idx) => (
<tr key={idx}>
<td>{id}</td>
<td>{name}</td>
</tr>
)
return (
<table>
<tr>
<th onClick={sortByKey('id')}>ID</th>
<th onClick={sortByKey('name')}>Name</th>
</tr>
{ data.map(renderRow) }
</table>
);
}
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {
sort: {
key: undefined,
// 0 - not ordering
// 1 - asc
// 2 - desc
order: 0,
},
};
this.sortByKey = this.sortByKey.bind(this);
}
sortedData() {
const { key, order } = this.state.sort;
// Only sort if key is provided & order != 0.
if (key && order) {
// Comparison function for "asc" sorting.
function compare(a, b) {
if (a[key] < b[key]) return -1;
if (a[key] > b[key]) return 1;
return 0;
}
// Attention! Sort mutates array, clone first.
return [...this.props.data].sort((a, b) => {
// Interesting part. Sort in "asc" order. Flip if want "desc" order!
return compare(a, b) * (order === 1 ? 1 : -1);
});
}
// Return original data (order = 0)
return this.props.data;
}
sortByKey(key) {
return () => {
const sort = (this.state.sort.key === key)
// Key matches, update order
? { key, order: (this.state.sort.order + 1) % 3 }
// Key differs, start with "asc" order
: { key, order: 1 };
this.setState({ sort });
}
}
render() {
return (
<Table data={this.sortedData()} sortByKey={this.sortByKey} />
);
}
}
ReactDOM.render(
<Container data={data} />,
document.getElementById('container')
);

dojo pattern - when to use set/watch and when to use notify/observe?

I'm struggling with a MVC pattern around Stateful objects and Observable stores. I can't find clarity on when to use one over another and mixing them isn't as clean as I'd hoped. Any Ah! insight into how to manage an observable collection of stateful items?
If I do a item.set("key", value) I can item.watch("key", cb) but then my observe-er isn't notify-ed.
I can do a item.watch(function() { state.notify(item, item.id); }) to always notify my observer but if my observe-er calls set I get a "Query is out of date, you must observe() the query prior to any data modifications'" error I cannot reconcile.
I can decouple this via a setTimeout but it's not feeling good.
Here's some code to show what I'm trying:
crudify: function ( store, query, crud )
{
var result;
if ( !crud )
{
crud = query;
query = store;
store = null;
}
if ( store )
{
query = store.query( query );
}
result = query.observe( function ( row, deleteIndex, insertIndex )
{
var del = ( 0 <= deleteIndex ), ins = ( 0 <= insertIndex );
!del && ins && crud.c && crud.c( row );
del && ins && crud.u && crud.u( row );
del && !ins && crud.d && crud.d( row );
}, !!crud.u );
crud.c && array.forEach( query, crud.c );
return result;
}
And I have a store wrapper (for layers) which I'm hacking to pieces trying to get the observe-ers notified of data changes without getting errors:
addLayer: function ( item ) {
var that = this;
that.store.add(item);
item.watch && item.watch(function (name, prior, curr) {
if (prior !== curr) {
that._queue.push(item);
// attempting to eliminate queries which indirectly update the store (can't find source of error)
infor.delay(20, "LayerProcessorStoreNotification", function () {
that._queue.forEach(function (item) {
that.store.notify(item, that.getLayerId(item));
});
that._queue = [];
});
}
});
return item;
},
The delay method looks like this:
delay: function ( timeout, id, callback )
{
this.delays = this.delays || [];
var delay = this.delays[id];
if ( delay )
{
clearTimeout( delay );
}
delay = setTimeout( callback, timeout );
this.delays[id] = delay;
},
I can do a item.watch(function() { state.notify(item, item.id); }) to always notify my observer
I didn't have any problems using this pattern, but...
but if my observe-er calls set I get a "Query is out of date, you must observe() the query prior to any data modifications'" error I cannot reconcile.
You shouldn't have watch call notify and also have observe call set. Choose one or the other. Otherwise you're setting yourself up for an infinite loop of callbacks.
The code below works for me. The only change I made to your crudify function was to change array.forEach(query, crud.c) to query.forEach(crud.c).
<script type="text/javascript" src="../javascripts/dojo-release-1.9.3-src/dojo/dojo.js"></script>
<script type="text/javascript">
window.stackoverflow = {
crudify: function ( store, query, crud )
{
var result;
if ( !crud )
{
crud = query;
query = store;
store = null;
}
if ( store )
{
query = store.query( query );
}
result = query.observe( function ( row, deleteIndex, insertIndex )
{
console.log("Observed");
var del = ( 0 <= deleteIndex ), ins = ( 0 <= insertIndex );
!del && ins && crud.c && crud.c( row );
del && ins && crud.u && crud.u( row );
del && !ins && crud.d && crud.d( row );
}, !!crud.u );
crud.c && query.forEach( crud.c );
return result;
}
};
require([
"dojo/store/Memory",
"dojo/store/Observable",
"dojo/Stateful",
"dojo/_base/json",
"dojo/domReady!"
], function(Memory, Observable, Stateful, dojo){
var store = Observable(new Memory({ data: [] }));
var rawData = [ { id: 1, data: "A" }, { id: 2, data: "B" }, { id: 3, data: "C" }]
var myQuery = { id : 3 };
rawData.forEach(function (obj, index) {
statefulObj = new Stateful(obj);
statefulObj.watch(function(name, oldValue, newValue) {
console.log("Watched");
store.notify(statefulObj, statefulObj.id);
});
store.put(statefulObj);
});
window.setTimeout(function() {
// this directly triggers the observe() callback
store.notify(store.get(3), 3);
}, 2000);
window.setTimeout(function() {
// this triggers the watch(), which indirectly triggers observe() through notify()
store.get(3).set("data", "Sea?");
}, 4000);
window.setTimeout(function() {
// this calls no callbacks because it doesn't match the query
store.put({ id: 2, data: "Bee" });
}, 6000);
window.setTimeout(function() {
// this update triggers observe()
store.put(new Stateful({ id: 3, data: "See!?!" }));
// note that we didn't set up a watch() on this new object (see below)
}, 8000);
window.setTimeout(function() {
// whoops, this doesn't trigger a callback because we forgot to call watch() above
store.get(3).set("data", "C4");
}, 10000);
window.setTimeout(function() {
// but the observe() callback still works
store.notify(store.get(3), 3);
}, 12000);
window.setTimeout(function() {
// this deletion triggers observe()
store.remove(3);
}, 14000);
stackoverflow.crudify(
store,
myQuery,
{
u: function(obj) {
console.log("Observed update: obj: " + dojo.toJson(obj));
},
c: function(obj) {
console.log("Observed creation: obj: " + dojo.toJson(obj));
},
d: function(obj) {
console.log("Observed deletion: obj: " + dojo.toJson(obj));
}
});
});
</script>

datatables pagination is broken when I add sType

Im using the date-euro plugin to sort the date column properly. the sort is working, but the pagination is going to broken on init when I add the sType parameter. when i click the numberofelement dropdown or on the next button, the pagination works. The prettydaterender function converts the date from 2012-10-24 14:00 to 24/10/2012 14:00
Could you help me please?
$.extend( $.fn.dataTableExt.oSort, {
"date-euro-pre": function ( a ) {
if ($.trim(a) != '') {
var frDatea = $.trim(a).split(' ');
var frTimea = frDatea[1].split(':');
var frDatea2 = frDatea[0].split('/');
var x = (frDatea2[2] + frDatea2[1] + frDatea2[0] + frTimea[0] + frTimea[1] + frTimea[2]) * 1;
} else {
var x = 10000000000000; // = l'an 1000 ...
}
return x;
},
"date-euro-asc": function ( a, b ) {
return a - b;
},
"date-euro-desc": function ( a, b ) {
return b - a;
}
} );
table.dataTable({
"sDom": "<'row'<'span6'l><'span6'f>r>t<'row'<'span6'i><'span6'p>>",
'aaSorting': [[3, 'desc']],
'aoColumns': [null,null,null,{
// 14:43 24/10/2012
'fnRender': prettyDateRender,
'sType': 'date-euro-desc'
}]
});

Resources