Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions web_x2many_list_scroll/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

=========================
Scrollable Lists in Forms
=========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:c7a24ce62f390f72d4c04a665b5337ede9447ab97677cb82c134966de269e480
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github
:target: https://github.com/OCA/web/tree/19.0/web_x2many_list_scroll
:alt: OCA/web
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/web-19-0/web-19-0-web_x2many_list_scroll
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

A list of lines inside a form (order lines, invoice lines, a catalogue
of requirements...) stretches the page as it grows: past a screen of
rows the column titles and the row of totals are out of sight, and the
user scrolls the whole page up and down to read them.

With this module the list scrolls by itself within a set number of rows,
in both directions, and its header and its totals stay in sight. The
pager of the list keeps working as before: each page scrolls within that
height.

The number of rows is set once for the whole database, and any form can
set its own number, or switch the behaviour off, on the field.

**Table of contents**

.. contents::
:local:

Configuration
=============

For the whole database
----------------------

Go to *Settings ▸ General Settings ▸ Lists in Forms ▸ Scrollable Lists*
and set *Visible rows*: the rows a list inside a form shows before it
scrolls. ``0`` (the default) leaves every list as it is.

The value is kept in the system parameter
``web_x2many_list_scroll.rows`` (*Settings ▸ Technical ▸ System
Parameters*, developer mode). It is read once per session: after
changing it, reload the page. Anything that is not a positive integer
counts as ``0``.

For one form
------------

On the field of the lines in the form view, add the option
``scroll_rows``:

.. code:: xml

<field name="order_line" options="{'scroll_rows': 15}">

It wins over the database setting. ``'scroll_rows': 0`` leaves that list
as it is even when the setting is on. The option only applies when the
field is shown as a list.

Row height
----------

The height of the box is the configured number of rows times the height
of a row as rendered, plus the header, both measured on the list itself,
so it follows the font, the density and the device (rows are taller on a
touch screen). They are exposed as the CSS custom properties
``--o-x2many-list-scroll-row-height`` and
``--o-x2many-list-scroll-header-height`` on the field. Rows with wrapped
text take more room than the first one, so a page with such rows shows
fewer of them.

Header above the rows
---------------------

Inside a form Odoo flattens the header of a list, so the tags, badges
and toggles of the rows rolling under it would paint over it. The module
lifts the header and the footer to the level of the CSS custom property
``--o-x2many-list-scroll-zindex`` (``2``). Native list widgets do not
stack above that; a custom widget that does can be tuned through that
property.

Usage
=====

Open a form whose lines exceed the configured rows, for instance a
purchase order or a vendor bill with many lines: the list shows the set
number of rows and scrolls within them, the column titles stay at the
top and the totals at the bottom while the rows roll. With more columns
than fit, the list also scrolls sideways within the same box.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/web/issues/new?body=module:%20web_x2many_list_scroll%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Jarsa

Contributors
------------

- Jarsa

- Alan Ramos <alan.ramos@jarsa.com>

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/web <https://github.com/OCA/web/tree/19.0/web_x2many_list_scroll>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions web_x2many_list_scroll/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
25 changes: 25 additions & 0 deletions web_x2many_list_scroll/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2026 Jarsa
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
{
"name": "Scrollable Lists in Forms",
"summary": "Lists inside forms scroll within a set number of rows, "
"header and totals staying in sight",
"version": "19.0.1.0.0",
"author": "Jarsa, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/web",
"license": "LGPL-3",
"category": "Web",
"depends": ["web", "base_setup"],
"data": ["views/res_config_settings_views.xml"],
"assets": {
"web.assets_backend": [
"web_x2many_list_scroll/static/src/js/x2many_field.esm.js",
"web_x2many_list_scroll/static/src/xml/x2many_field.xml",
"web_x2many_list_scroll/static/src/scss/x2many_field.scss",
],
"web.assets_unit_tests": [
"web_x2many_list_scroll/static/tests/*",
],
},
"installable": True,
}
83 changes: 83 additions & 0 deletions web_x2many_list_scroll/i18n/es.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_x2many_list_scroll
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 19.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-09-17 20:02+0000\n"
"PO-Revision-Date: 2026-09-17 20:02+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#. module: web_x2many_list_scroll
#: model:ir.model,name:web_x2many_list_scroll.model_res_config_settings
msgid "Config Settings"
msgstr "Ajustes de configuración"

#. module: web_x2many_list_scroll
#: model:ir.model.fields,field_description:web_x2many_list_scroll.field_ir_http__display_name
#: model:ir.model.fields,field_description:web_x2many_list_scroll.field_res_config_settings__display_name
msgid "Display Name"
msgstr "Nombre mostrado"

#. module: web_x2many_list_scroll
#: model:ir.model,name:web_x2many_list_scroll.model_ir_http
msgid "HTTP Routing"
msgstr "Enrutamiento HTTP"

#. module: web_x2many_list_scroll
#: model:ir.model.fields,field_description:web_x2many_list_scroll.field_ir_http__id
#: model:ir.model.fields,field_description:web_x2many_list_scroll.field_res_config_settings__id
msgid "ID"
msgstr "ID"

#. module: web_x2many_list_scroll
#: model_terms:ir.ui.view,arch_db:web_x2many_list_scroll.res_config_settings_view_form
msgid "Lists in Forms"
msgstr "Listas en formularios"

#. module: web_x2many_list_scroll
#: model_terms:ir.ui.view,arch_db:web_x2many_list_scroll.res_config_settings_view_form
msgid ""
"Lists of lines inside forms (order lines, invoice lines...) scroll within "
"this number of rows instead of stretching the page, so their header and "
"totals stay in sight. 0 leaves them as they are."
msgstr ""
"Las listas de líneas dentro de los formularios (líneas de pedido, de "
"factura...) hacen scroll dentro de este número de filas en vez de estirar la"
" página, así su encabezado y sus totales quedan a la vista. 0 las deja como "
"están."

#. module: web_x2many_list_scroll
#: model:ir.model.fields,help:web_x2many_list_scroll.field_res_config_settings__web_x2many_list_scroll_rows
msgid ""
"Rows a list inside a form shows before it scrolls, with its header and its "
"totals staying in sight. 0 leaves the lists as they are. A form can set its "
"own number, or 0, on the field with options=\"{'scroll_rows': 15}\"."
msgstr ""
"Filas que muestra una lista dentro de un formulario antes de hacer scroll, "
"con su encabezado y sus totales a la vista. 0 deja las listas como están. Un"
" formulario puede fijar su propio número, o 0, en el campo con "
"options=\"{'scroll_rows': 15}\"."

#. module: web_x2many_list_scroll
#: model_terms:ir.ui.view,arch_db:web_x2many_list_scroll.res_config_settings_view_form
msgid "Scrollable Lists"
msgstr "Listas con scroll"

#. module: web_x2many_list_scroll
#: model:ir.model.fields,field_description:web_x2many_list_scroll.field_res_config_settings__web_x2many_list_scroll_rows
msgid "Visible Rows in Form Lists"
msgstr "Filas visibles en listas de formularios"

#. module: web_x2many_list_scroll
#: model_terms:ir.ui.view,arch_db:web_x2many_list_scroll.res_config_settings_view_form
msgid "Visible rows"
msgstr "Filas visibles"
2 changes: 2 additions & 0 deletions web_x2many_list_scroll/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import ir_http
from . import res_config_settings
25 changes: 25 additions & 0 deletions web_x2many_list_scroll/models/ir_http.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2026 Jarsa
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
from odoo import models

PARAM_ROWS = "web_x2many_list_scroll.rows"


class IrHttp(models.AbstractModel):
_inherit = "ir.http"

def session_info(self):
session = super().session_info()
session["web_x2many_list_scroll_rows"] = self._web_x2many_list_scroll_rows()
return session

def _web_x2many_list_scroll_rows(self):
"""Rows a list inside a form shows before it scrolls.

0 leaves the lists as they are.
"""
value = self.env["ir.config_parameter"].sudo().get_param(PARAM_ROWS, "0")
try:
return max(int(value), 0)
except ValueError:
return 0
18 changes: 18 additions & 0 deletions web_x2many_list_scroll/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 Jarsa
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
from odoo import fields, models

from .ir_http import PARAM_ROWS


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

web_x2many_list_scroll_rows = fields.Integer(
string="Visible Rows in Form Lists",
config_parameter=PARAM_ROWS,
help="Rows a list inside a form shows before it scrolls, with its header "
"and its totals staying in sight. 0 leaves the lists as they are. A "
"form can set its own number, or 0, on the field with "
"options=\"{'scroll_rows': 15}\".",
)
3 changes: 3 additions & 0 deletions web_x2many_list_scroll/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
40 changes: 40 additions & 0 deletions web_x2many_list_scroll/readme/CONFIGURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## For the whole database

Go to *Settings ▸ General Settings ▸ Lists in Forms ▸ Scrollable Lists* and
set *Visible rows*: the rows a list inside a form shows before it scrolls.
`0` (the default) leaves every list as it is.

The value is kept in the system parameter `web_x2many_list_scroll.rows`
(*Settings ▸ Technical ▸ System Parameters*, developer mode). It is read once
per session: after changing it, reload the page. Anything that is not a
positive integer counts as `0`.

## For one form

On the field of the lines in the form view, add the option `scroll_rows`:

```xml
<field name="order_line" options="{'scroll_rows': 15}">
```

It wins over the database setting. `'scroll_rows': 0` leaves that list as it
is even when the setting is on. The option only applies when the field is
shown as a list.

## Row height

The height of the box is the configured number of rows times the height of a
row as rendered, plus the header, both measured on the list itself, so it
follows the font, the density and the device (rows are taller on a touch
screen). They are exposed as the CSS custom properties
`--o-x2many-list-scroll-row-height` and `--o-x2many-list-scroll-header-height`
on the field. Rows with wrapped text take more room than the first one, so a
page with such rows shows fewer of them.

## Header above the rows

Inside a form Odoo flattens the header of a list, so the tags, badges and
toggles of the rows rolling under it would paint over it. The module lifts the
header and the footer to the level of the CSS custom property
`--o-x2many-list-scroll-zindex` (`2`). Native list widgets do not stack above
that; a custom widget that does can be tuned through that property.
2 changes: 2 additions & 0 deletions web_x2many_list_scroll/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Jarsa
- Alan Ramos \<alan.ramos@jarsa.com\>
11 changes: 11 additions & 0 deletions web_x2many_list_scroll/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
A list of lines inside a form (order lines, invoice lines, a catalogue of
requirements...) stretches the page as it grows: past a screen of rows the
column titles and the row of totals are out of sight, and the user scrolls the
whole page up and down to read them.

With this module the list scrolls by itself within a set number of rows, in
both directions, and its header and its totals stay in sight. The pager of
the list keeps working as before: each page scrolls within that height.

The number of rows is set once for the whole database, and any form can set
its own number, or switch the behaviour off, on the field.
5 changes: 5 additions & 0 deletions web_x2many_list_scroll/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Open a form whose lines exceed the configured rows, for instance a purchase
order or a vendor bill with many lines: the list shows the set number of rows
and scrolls within them, the column titles stay at the top and the totals at
the bottom while the rows roll. With more columns than fit, the list also
scrolls sideways within the same box.
Loading
Loading