ExtJS 6.2 Sort grid Panel groupings based on summary row - extjs

I've been searching for hours to figure out how to do this. Essentially what I want to do is group data based on one column, create a summary for that grouping, then sort the groups based on the summary.
Using one of their kitchen sink examples, I would like to be able to sort these groups by summary value rate.
http://examples.sencha.com/extjs/6.0.0/examples/classic/grid/group-summary-grid.html

This can be done using a grouper with a sorterFn. The sorterFn should compare the summary values you are sorting by. For the kitchen sink example you mentioned, if you want to sort by the sum of the estimate column while grouping by the project column, the grouper would look like:
groupers: [{
property: 'project',
sorterFn: function(a,b) {
var suma=0; store.each(function (rec) { suma += rec.data.project === a.data.project ? rec.data.estimate:0; });
var sumb=0; store.each(function (rec) { sumb += rec.data.project === b.data.project ? rec.data.estimate:0; });
if (suma > sumb) return 1;
if (suma < sumb) return -1;
return 0;
}
}]
The grouper can be applied using:
store.group(store.groupers[0]);
See fiddle: https://fiddle.sencha.com/#fiddle/1im3

Related

Adding a custom "ALL" (Total) row to the top of an ag-grid that is selectable like any other row

I have an ag-grid table with 2 columns - one text and one number.
I need to add a custom row to the top of my ag-grid table with the total value of the number column and the word "ALL" in the text column.
This needs to be on the top. And should not change its position even if the table is sorted.
Also, the row should be selectable.
Any help in this regard will be highly appreciated!
Sounds like you are describing Row Pinning which is already a feature in AG Grid. However, since you've also stated that row selection is a requirement, this will not be possible with Row Pinning as it's not supported.
Instead what I'd recommend is adding an extra row object inside the rowData for the custom row, and handling the update of the number column and the custom row position yourself when necessary:
If you want to handle the total value of the number column then you can use the following logic:
function updateTotalRowNode() {
let totalRowNode;
let sum = 0;
gridOptions.api.forEachNode((node) => {
if (node.data.totalRow) {
totalRowNode = node;
} else {
sum += node.data.gold;
}
});
totalRowNode.setDataValue('gold', sum);
}
If you want to keep the custom row always on the top row then you can implement the postSort callback:
postSort: (rowNodes) => {
// here we put All row on top while preserving the sort order
let nextInsertPos = 0;
for (let i = 0; i < rowNodes.length; i++) {
const athlete = rowNodes[i].data.athlete;
if (athlete === 'All') {
rowNodes.splice(nextInsertPos, 0, rowNodes.splice(i, 1)[0]);
nextInsertPos++;
}
}
},
See the following plunker for the implementation.

ag-Grid: use floatingBottomRowData when Pivoting

I'm trying to recreate the following pivot table with ag-Grid:
Using floatingBottomRowData I can't find a way to pass the values for all generated columns. so one pair of values is getting duplicated:
My goal is to access the column group value for each cell of the floating row.
Right now I can't tell the difference between column groups (resulting in duplicated values).
Is there any way to differentiate the different (col1, col2) pairs?
The answer that was given in the ag-grid forum is:
to get the pivot key, do this:
floatingCellRenderer: function(params) {
if (gridOptions.columnApi.isPivotMode()) {
console.log(params.column.getId());
var parent = params.column.getParent();
if (parent) {
var pivotKey = console.log(parent.getOriginalColumnGroup().getColGroupDef().pivotKeys[0]);
}
}
}
to get the columns in the active pivot, use the column API, eg columnApi.getPivotColumns(), which will return a list of the pivot columns. this will be in order, so if you have many columns, there will be one for each parent you traverse.
What I did for the pivot_ type of pinned row: I added a custom pinned row renderer to my column, where I expect the aggregated function to show (for me it was for sum and avg). If I change the pivot function I called a refresh on the pinned row to set the new values.
pinnedRowCellRenderer: function (render)
{
for (var obj_id in render.data)
{
if (obj_id == render.column.colId)
{
return '<div>' + render.data[obj_id] + '</div>';
}
}
return '<div></div>';
}
And the result looks like this:
Result image
Hope it helps!

Programmatically change grid column order

I want to sort the columns in my grid, just like the rows. I have made a simple sort function that is called from an actioncolumn handler:
sortColumns:function(record) { // The record after which's values the columns are ordered
var columns = this.columns;
Ext.Array.sort(columns,function(col1,col2) {
if(record.get(col1.dataIndex) > record.get(col2.dataIndex)) return 1;
if(record.get(col1.dataIndex) < record.get(col2.dataIndex)) return -1;
if(col1.dataIndex > col2.dataIndex) return 1;
if(col1.dataIndex < col2.dataIndex) return 1;
throw new Error("Comparing column with itself shouldn't happen.");
});
this.setColumns(columns);
});
The setColumns line now throws the error
Cannot add destroyed item 'gridcolumn-1595' to Container 'headercontainer-1598'
which is because the "old" columns are destroyed first, and then the "new" columns, which are the same and thus destroyed, are applied.
I only want to change the order, but I didn't find any function to do it. Do you know how to do it?
Drag-drop ordering of the columns works, so it is doable; but I don't find the source code where sencha did implement that drag-drop thingy. Do you know where to look for that code?
Reconfigure method needs two arguments
grid.reconfigure(store, columns)
Here is the fiddle that changes the columns programatically https://fiddle.sencha.com/#fiddle/17bk
I have found that columns are items of the grid's headerCt, so the following works well, and unlike the other answers, it does not create new column components, keeping the column state and everything:
var headerCt = normalGrid.headerCt,
columns = headerCt.items.getRange();
Ext.Array.sort(columns,function(col1,col2) {
if(record.get(col1.dataIndex) < record.get(col2.dataIndex)) return -1;
if(record.get(col1.dataIndex) > record.get(col2.dataIndex)) return 1;
if(col1.dataIndex < col2.dataIndex) return -1;
if(col1.dataIndex > col2.dataIndex) return 1;
return 0;
});
headerCt.suspendLayouts();
for(var i=0;i<columns.length;i++)
{
headerCt.moveAfter(columns[i],(columns[i-1] || null));
}
headerCt.resumeLayouts(true);
There is a reconfigure method which can be used to achieve reordering, e.g:
grid.reconfigure(columns);
Check the this.
I couldn't manage to do it without storing columns in a custom field and using reconfigure, maybe someone can suggest something better (reconfigure doesn't work well with just regular columns field it seems):
Ext.define('MyGrid', {
extend: 'Ext.grid.Panel',
//just renamed "columns"
myColumnConfigs: [
//all your column configs
]
});
//to rearrange inside controller, also need to call it on grid render
var grid = this.getView();
var columns = grid.myColumnConfigs;
//...do your sorting on columns array
grid.reconfigure(columns);

Split list of countries in alphabetical order using Angularjs

I want to split a list of countries in alphabetical order using Angularjs.
Somewhat like A : America , Australia B: Brazil, Bhutan ...
The list is coming from a table named countries. I tried to apply angularjs filter on the first alphabet of the country name but failed. Do I have to create a custom filter for it?
Ok I am going to answer my own question finally got it working.
I was pulling a list of countries from a postgres db in the following format:
{"alpha2":"ao","alpha3":"ago","numeric":"024","country":"Angola"}
I wanted to split the list of countries in alphabetical order like this :
[Example] http://infoplease.com/countries.html#ALPHA-A
I finally got it working by writing a custom filter:
angular.module('countryFilter', []).filter('cfilter', function() {
return function(input,x) {
var groups = [];
for(var i = 0; i < input.length; i++) {
if (input[i].country.substring(0,1) == x)
groups.push(input[i]);
} return groups; }
});
and using it as :
ng-repeat="data in countries | cfilter:'A'
{{data.country}}
Do let me know if there is any better way for doing this...
This is another possible solution without the use of a filter
http://www.bennadel.com/blog/2456-Grouping-Nested-ngRepeat-Lists-In-AngularJS.htm
He creates a new array with a label and the data. The advantage is that in the template you don't have to name all the possible letters.
For my own I take the first letter of the client from the object and store that in the label. In that way I only get the letters I used.
In customer I have stored an array with objects.
for(var i = 0; i < customers.length; i++){
var customer = customers[i];
if(customer[ 'title' ].substring(0,1) !== groupValue){
var group = {
label : customer[ 'title' ].substring(0,1),
customers : []
};
groupValue = customer.title.substring(0,1);
groups.push( group );
};
group.customers.push( customer );
};
Sort Item List is a jQuery plugin that creates iOS-style sticky headers similar to those seen in the Music and Contacts apps on Apple devices
check link :
http://www.codingprogrammer.com/tutorialdemo/jquery-tutorial/sort-items-alphabetically-jquery-2/

How to calculate total of one field in the store

I have a grid within a form as in the attached image. When the the customer name is changed, then the grid store is loaded with records corresponding to the customer. I want the balance textfield to be populated with the sum of Amount due column.
The image is here.
Use like this:
store.load({
scope : this,
callback: function(records, operation, success) {
//here the store has been loaded so you can use what functions you like.
//This code sum numbers in certain column
sum = 0;
store.each(function (rec) { sum += rec.get('NameColumn'); });
}
});
Use the store summary function:
var sum = grid.getStore().sum('NameColumn');
sencha api: sum store

Resources