dynamic_selection
A selection field always offers every value it declares, unless you render it with dynamic_selection, the small account-module widget that shows only the options another field on the record allows. Odoo's e-invoicing localizations run on it.
| Technical name | dynamic_selection |
|---|---|
| Field types | selection |
| Views | form, list |
| Module | account, so any database running Invoicing has it |
| Used in core | 19 occurrences across 6 modules, including l10n_gr_edi, l10n_ro_edi_stock_batch, l10n_ro_edi_stock, account_qr_code_emv, l10n_es_edi_verifactu, l10n_fr_pdp |
| Versions | Odoo 20.0, Odoo 19.0, Odoo 18.0 |
| No-code setup | No. The widget and its companion field are wired in view and model code |
| Alternatives | selection, selection_badge, radio |
What the Dynamic Selection widget does
What this means for your team
Supported options in Odoo 19
| Option | Type | What it does |
|---|---|---|
available_field | field name | Required. Names a char field on the record containing the allowed selection keys, comma separated. Only declared selection values whose key is in that list are offered; an empty list means an empty dropdown. |
placeholder_field | field name | Inherited from the base selection descriptor: reads the placeholder text from another char field on the record. |
The allowed values are keys, not labels. The char field must contain the technical selection keys, comma separated with no decoration: a,b,c. A stored value that is not in the current allowed list does not crash the view; the source's optional chaining renders it as blank in readonly, which is easy to misread as data loss. The value is still in the database.
Working examples
Why readonly can render blank
Version compatibility
| Version | Status | Notes |
|---|---|---|
| Odoo 20.0 | In development | Not released. No changes visible on the development branch; see below. |
| Odoo 19.0 | Verified | Verified against the shipped account module source. |
| Odoo 18.0 | Verified | The 18.0 and 19.0 files are byte-identical. Verified directly. |
What is changing in Odoo 20
Common problems and fixes
| Symptom | Cause and fix |
|---|---|
| The dropdown is empty | The available_field is empty, not loaded in the view, or its keys do not match the selection keys exactly. Put the available field in the view (column_invisible works), and check the compute writes exact keys, comma separated, no spaces or brackets. |
| Readonly cell shows nothing although a value is stored | The stored value is no longer in the allowed list; the widget renders blank instead of crashing. Either accept it (the data is intact), extend the allowed list to include legacy values, or migrate old records to valid keys. |
| Options do not update after changing the driving field | The available field is not recomputed in the browser, usually a missing @api.depends trigger. Add the driving fields to the compute's depends so the allow list refreshes with the record. |
| TypeError mentioning available_field | The option is missing; the widget declares the prop as required and has no show-everything fallback. Always pass options="{'available_field': '...'}"; for an unfiltered dropdown use the plain selection widget. |
| Kanban clicks save the record immediately | Inherited base-selection behavior: autosave is enabled for kanban views in extractProps. Expected. Keep the field off kanban cards if immediate writes are unwanted. |
Dynamic Selection widget vs the alternatives
| Widget | Best for | Key difference |
|---|---|---|
dynamic_selection | Legal code lists and other per-record option subsets | Dropdown contents driven by a comma separated allow list on the record |
selection | Selections whose options never depend on the record | Always offers every declared value |
| selection_badge | Short selections picked at a glance | Renders options as pill buttons, no per-record filtering |
| radio | A handful of always-visible choices | All options rendered as radio buttons, no filtering |
Frequently asked questions
How do I show different selection options per record in Odoo?+
Does dynamic_selection change what can be stored?+
What happens to records whose stored value is no longer allowed?+
Why does core only use this in localization modules?+
Can I use it on a many2one field?+
Does it work in list views?+
Fighting a government code list right now?
myDATA, Veri*Factu, e-Transport, PEPPOL: e-invoicing mandates all come down to sending the right code from the right subset. We build and localize Odoo compliance flows, computed allow lists, validation constraints and the EDI plumbing behind them, so rejections stop reaching your accountants.
Book a free consultation