Grouping in a V7 form

50 views
Skip to first unread message

Volker Trapp

unread,
Dec 18, 2025, 8:54:57 AM12/18/25
to Jam.py Users Mailing List
I would like to group on a field in a form. I have tried to something like this


function on_view_form_created(item) {
    var grid = item.view_grid;

    grid.options.group_by = 'projektnummer';
}

but it is not the right way.
What is the way to get a grouped tableview in V7 ?grouping.PNG

Dean Babic

unread,
Dec 18, 2025, 9:56:39 AM12/18/25
to Jam.py Users Mailing List
Filters?

Volker Trapp

unread,
Dec 18, 2025, 10:44:18 AM12/18/25
to Jam.py Users Mailing List
no grouping.

Filters will only show f.e. one project.
I want to have it grouped by project

Dean D. Babic

unread,
Dec 18, 2025, 7:31:28 PM12/18/25
to Jam.py Users Mailing List
Could you describe more pls? 
Your pic has one record. Not sure how to conclude anything from it.

If you check a filter here:
https://jampy.pythonanywhere.com/
The filter is doing exactly that.

Volker Trapp

unread,
Dec 19, 2025, 1:47:58 AM12/19/25
to Jam.py Users Mailing List
Hi Dean,

I do not see how this can be done with a filter.
Grouping is a special view on all data, while filtering is a partly view on data.

in the attached picture you can see a tableview with two groupings:
1. Group on project ( Projektnummer )
2. inside Group 1 a group on a part or article ( Anlagenbezeichnung )

grouping.PNG

Dean D. Babic

unread,
Dec 19, 2025, 2:13:34 AM12/19/25
to Jam.py Users Mailing List
Hi Volker,

IMO now we can see that this is the data problem. 
What would be great to show is the table referential, not the UI result on the screen.

I think this is somehow related to classic BOM application, like this one:
https://billsofmaterials.pythonanywhere.com/

Jam would be using KEYS type for your articles. We see this with "selected:1" etc with 
details/sub details. I did not finish this app as per this thread:
https://groups.google.com/g/jam-py/c/avH0dELfSPE/m/kmD8I8rfAgAJ

What you are showing is some other "engine" to display this data. 
This is quite complex App migration.

r rad

unread,
Dec 19, 2025, 4:20:02 AM12/19/25
to Jam.py Users Mailing List
Hi there,
If this is edit page, it may be a problem. 
Edit template for this page have to changed, and from javascript doing rest.

If this page is report  it can being do, with nested report level.

PS. This problem can resolved some professional tools, i think.

Radosav.

Volker Trapp

unread,
Dec 19, 2025, 8:53:35 AM12/19/25
to Jam.py Users Mailing List
@Dean
Thanks I will think about the BOM Format you used. Probably I have to go a different way.

@Radosav
It is not an edit page since data is comming from a view. But Details wil be editable.
Still I do not understand what you mean by "can be done with nested reports" ?

r rad

unread,
Dec 19, 2025, 9:07:10 AM12/19/25
to Jam.py Users Mailing List
With nested level of report.

Each report can have pages, and pages can have section, and subsection, etc...,
each of them you can control via break value of some variable, by your choose.
Python programming + SQL + a little formatting output. 
Nothing especially.

r rad

unread,
Dec 19, 2025, 9:27:04 AM12/19/25
to Jam.py Users Mailing List
Volker,

Hm, if you want editable details, this is a little complicated.
You must having id for each row of parents!?!
If its true, that not be a report! 
Report have not id, for each time its may be diff ( RDBMS's don't garantee order ). 
You must have hard id value, because the relation with details.

Radosav

Drazen Babic

unread,
Dec 19, 2025, 9:55:34 AM12/19/25
to Volker Trapp, Jam.py Users Mailing List

Some JS tree plugin might be used, but then it would not be a native Jam feature and style, probably missing CRUD.
This is the same issue with using Datatables, looks ok, but missing a lot. Depends what is needed tho. If is just a view, fine. But then, adding editabe Details in DTables is a bugger.
DT is all html, not JS - hence, no events.

The problem is, Jam works with a JS grid. And u have a nested grids, with almost like a tree dependency. And then u also have some possible calculation. To me, this is a domain of an ERP. 

I do not recall a similar view even with the official Jam video. 

A report might be possible to develop. LibreOffice Calc is used, I guess u know that.
Northwind app has one yearly report. 

BR

On Fri, 19 Dec 2025 at 9:53 pm, 'Volker Trapp' via Jam.py Users Mailing List <jam...@googlegroups.com> wrote:
@Dean
Thanks I will think about the BOM Format you used. Probably I have to go a differentnt way.
--
You received this message because you are subscribed to the Google Groups "Jam.py Users Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jam-py+un...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/jam-py/6409c989-cf68-4b11-87e4-89b4ef315e5an%40googlegroups.com.

Dean D. Babic

unread,
Dec 19, 2025, 10:22:47 AM12/19/25
to Jam.py Users Mailing List
Here is one JS tree:
https://www.ag-grid.com/javascript-data-grid/tree-data/

How do we know that this might work? Try to select all with CTRL+A.
What do you see?

Now try this one:
https://primeng.org/treetable 

What do you see? Sorry if it is obvious, but some readers might not know.
So Jam would need:
<script src="https://cdn.jsdelivr.net/npm/ag-grid-...@35.0.0/dist/ag-grid-community.min.js"></script>
and the code to make your nested tree.
Now look at the prices:
https://www.ag-grid.com/license-pricing/

So, can anyone enlighten me why is Jam still free? ;) 

Dean D. Babic

unread,
Dec 21, 2025, 9:29:37 PM12/21/25
to Jam.py Users Mailing List
Here you go, grouping with AG library, on Analytics/AG:

https://jampy.pythonanywhere.com/

ag-grid-community_grouping_jampy.png
The data are static, not from the database - just an example.

I also added Catalogs/Get Invoice Sales, which is a Virtual Table with data from the Server Module.
The same principle can be used to feed above AG-grid library. Or any JS library or Jam grid.

D.


Dean D. Babic

unread,
Dec 21, 2025, 9:49:34 PM12/21/25
to Jam.py Users Mailing List
And here is a Server Module which DOES correct grouping and passing the data to library (use below in show_sales_grid):
def get_sales_2(item):
    """
    Return parent + child rows for Jam.py + AG Grid Community
    Flattened hierarchy with level + parent fields
    """
    customers = task.invoices.copy()
    invoices_ds = task.invoices.copy()  

    customers.open(
        fields=['id', 'customer', 'firstname', 'total'],
        funcs={'total': 'sum'},
        group_by=['customer'],
        order_by=['customer']
    )

    res = []

    for rec in customers:
        # Parent row (customer)
        parent_row = {
            'id': rec.customer.value,  # unique customer ID
            'name': f"{rec.firstname.lookup_value} {rec.customer.lookup_value}",
            'total': round(rec.total.value, 2),
            'level': 0,
            'parent': None,
            'visible': True,
            'expanded': False  # initially collapsed
        }
        res.append(parent_row)

        # Child rows (individual invoices)
        invoices_ds.open(fields=['id', 'total', 'customer'], order_by=['id'])
        for inv in invoices_ds:
            if inv.customer.value == rec.customer.value:
                child_row = {
                    'id': inv.id.value,             # invoice number
                    'name': f"INV-{inv.id.value}",  # display invoice number
                    'total': round(inv.total.value, 2),
                    'level': 1,
                    'parent': rec.customer.value,
                    'visible': False  # initially hidden
                }
                res.append(child_row)

    return res

Which produces below. Compare results with Demo for ie: Julia Barnett.
The same data we would get by Searching on Invoices for Customer Barnett.

The above is completely done by ChatGPT, so really there is nothing stopping
anyone to extend the Jam features. 

THE ONLY THING WE NEED TO HOW TO ADD LIBRARY AND SET THE TEMPLATE!
Everything else is AI trail and error.


ag-grid-community_grouping_server_module_jampy.png
Template (height/width is questionable here, but anyway):
<div class="ag-view">
    <div id="myGrid" class="form-body ag-theme-alpine" style="height:800px; width:100%"></div>
</div>

index:
ag-grid-community_library_jampy.png

AG empty virtual table (similar to Dashboard):
        function on_view_form_created(item) {
             show_sales_grid(item);
        }

        function show_sales_grid(item) {

            // Call server to get Python data
            item.server('get_sales_2', function(rowData) {

                agGrid.ModuleRegistry.registerModules([
                    agGrid.ClientSideRowModelModule
                ]);

                function renderGrid() {
                    var gridDiv = document.getElementById('myGrid');

                    // Destroy old grid if exists
                    if (gridDiv.__agGridInstance) {
                        gridDiv.__agGridInstance.destroy();
                    }

                    // Create new grid
                    var gridInstance = agGrid.createGrid(gridDiv, {
                        theme: 'legacy',
                        columnDefs: [
                            {
                                field: 'name',
                                headerName: 'Customer / Invoice',
                                cellRenderer: function(params) {
                                    var indent = (params.data.level || 0) * 20;
                                    var icon = '';
                                    if (params.data.level === 0) {
                                        icon = params.data.expanded ? '▾ ' : '▸ ';
                                    }
                                    var div = document.createElement('div');
                                    div.style.paddingLeft = indent + 'px';
                                    div.style.cursor = 'pointer';
                                    div.innerHTML = icon + params.value;

                                    if (params.data.level === 0) {
                                        div.onclick = function() {
                                            rowData.forEach(function(r){
                                                if (r.parent === params.data.id) {
                                                    r.visible = !r.visible;
                                                }
                                            });
                                            params.data.expanded = !params.data.expanded;
                                            renderGrid(); // safely re-render
                                        };
                                    }
                                    return div;
                                }
                            },
                            {
                                field: 'total',
                                headerName: 'Total',
                                valueFormatter: function(params) {
                                    return params.value != null ? params.value.toFixed(2) : '';
                                }
                            }
                        ],
                        rowData: rowData.filter(r => r.visible !== false),
                        rowSelection: { type: 'single', enableClickSelection: false }
                    });

                    // Save instance for next destroy
                    gridDiv.__agGridInstance = gridInstance;
                }

                renderGrid(); // initial render
            });
        }

All the best and this concludes my efforts for this year !

D.

Volker Trapp

unread,
Dec 22, 2025, 3:31:06 AM12/22/25
to Jam.py Users Mailing List
Thanks Dean,

what a great job ! I will need some time to check this.

Dean D. Babic

unread,
Dec 22, 2025, 5:56:01 AM12/22/25
to Jam.py Users Mailing List
You welcome

It goes even deeper, 3rd level:

ag-grid-community_grouping_server_module_level3_jampy.png

As I mentioned, this is not a Jam issue. This is a JS library concept. 
Jam.py only sets the SQL and the template.
As I see it, the tree does not close properly, it will leave 3rd level displayed, but remove 2nd level.
Something to fix.

Reply all
Reply to author
Forward
0 new messages