17.0 quick group by
Purpose
Add a compact, toggleable group-by button to list/tree view column headers so users can quickly group by a single field from the header.
Technical summary
- Patch
web.views.list.ListRendererto add:isColumnGroupable(column)— checks field metadata and excludesone2many,many2many, and non-stored computed fields.isColumnCurrentlyGrouped(column)— detects if the list is currently grouped bycolumn.name(single-level grouping).getButtonStyle(column)— returns inline style string for the header button.onGroupByColumn(ev)— toggles grouping by the clicked field, triggersmodel.load({ groupBy }), and updates header button UI (icons, colors, brief scale animation, hover styles).
- UI insertion uses a small QWeb template that renders a button next to column labels in list headers.
- Updates the visible state of all header buttons after model reload using a short delayed DOM update.
Files touched
static/src/js/list_header_cell.js— JS patch toListRenderer.static/src/xml/list_header_cell.xml— QWeb template injecting the header button.__manifest__.py— module metadata and assets bundle registration.
Checklist
- [x] No debug
console.log/console.warnin committed code. - [ ] Tests added / updated (none included in this PR).
- [x] Manual test steps included below.
- [x] Signed the OCA contribution form (CLA).
Manual testing steps
- Install the module.
- Open any list/tree view that contains a stored, non-relational field (e.g., a text, selection, or Many2one column).
- Verify a small toggle button appears to the right of the column label for groupable columns.
- Click the button:
- If the list is not grouped by that field, the view reloads grouped by the field.
- If the list is already grouped by that field, grouping is cleared.
- Confirm that relational columns (
one2many,many2many) and known non-stored computed fields do not show the button.
Notes for reviewers
- This patch intentionally supports only single-level grouping from the header (toggles between
[]and[field]). - Styling and icons use standard Font Awesome classes available in Odoo backend themes. If your environment uses custom icon sets, icons may differ.
- If you want automated coverage, I can add a minimal JS integration test that asserts
model.root.groupBychanges after a simulated click.
Limitations / design decisions
- Conservative metadata checks: if field metadata is missing or incomplete, the button will not be rendered to avoid unsafe grouping.
- The UI update after
model.loadis performed via a shortsetTimeoutto synchronize with the renderer lifecycle; if maintainers prefer, this can be refactored to a more robust event-hook approach.
Related issues / PRs
- (none)
Hi @MD-Jafor-Sadek-Khan. Thanks for sharing.
- could you follow OCA rules, regarding readme fragment files ?
- I tested on runboat, and nothing appears. Could provide a printscreen. I'm not sure to understand.
regards.
Hi @legalsylvain ,
Thanks for your feedback. I’ve verified the module according to OCA guidelines regarding README fragment files. The readme fragments are included under the readme/ folder and are automatically processed to generate the main README.rst and documentation.
I’ve also tested the module on Runboat, and the group-by toggle button appears correctly in list views (e.g., Contacts, Sales, Inventory) for groupable columns. Please see the attached screenshot for reference. Note that in a small number of list views (e.g., Invoice, Bills, Credit Notes, Refunds), the button may not appear due to templates being replaced in the Odoo community code.
Let me know if any additional adjustments are needed.
Regards, MD Jafor Sadek Khan
Hi @MD-Jafor-Sadek-Khan, thanks for your contribution!
I've been testing the approach and seems to work, however I think there are some issues:
- This completely ignores the group_by.
- It does not save for future searches (with default group by you can set a Favorite).
- In Date fields, you cannot choose between year, month, day, etc.
- Having the button position defined by where the label is (sometimes in the right side and sometimes in the left side) is a little bit confusing.
I think the idea is great, but I would prefer it as included in the default group by (to be able to use the already defined features.)
Thanks @DavidJForgeFlow — really useful feedback. I intentionally kept the controls in the column headers because they’re column-scoped actions: keeping them there ties the control to the column and improves discoverability for users. Moving them out of the header would change established interaction patterns, so I’d prefer to keep them in place by default.
I do agree with your technical points and will address them:
- include this in the default group_by options so it can be saved as a Favorite,
- persist user selections,
- add date-granularity choices (Year / Quarter / Month / Week / Day) for date fields, and
- normalize header button placement so it’s consistently right-aligned.
I can also add an optional user preference to move these controls to a global toolbar if you or others prefer that later — but by default they will remain header-based for discoverability. Thanks again for the detailed review.