Skip to main content
iVentureTeam

selection

The default dropdown behind every Selection field in Odoo, and the widget that turns a many2one into a closed list. How it works, what it hides, and where it trips teams up.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 12, 2026Updated August 12, 20268 min read
Odoo 19 form view showing a Selection field rendered by the selection widget as an open dropdown menu with a list of predefined choices and the current value highlighted.
Studio nameSelection
Technical nameselection
Field typesmany2one, selection
Viewsform, list, kanban
Moduleweb, present in every Odoo database
Used in core15 explicit occurrences across 12 modules, including web, loyalty, crm_iap_mine, website_slides, l10n_in_ewaybill, l10n_es_edi_tbai, plus every Selection field that names no widget at all
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupYes, via Odoo Studio (Enterprise)
Alternativesradio, selection_badge, statusbar, priority

What the Selection field does

Every Selection field in Odoo that does not name another widget renders through this one. It draws a closed dropdown of the values defined on the field, shows the label of the current value, and writes the chosen value back on change. Since Odoo 19 the dropdown is Odoo's own SelectMenu component rather than the browser's native select, which is why it now looks consistent across browsers and opens as a bottom sheet on small touch screens.

The less known half: point it at a many2one and it becomes a closed pick list of related records. It fires one name_search on the relation, honoring the field's domain, and renders the results as plain choices. No autocomplete, no Create option, no record opening. That is exactly what you want when a relation has a handful of stable rows and the full many2one experience is overkill.

What this means for your team

Dropdowns are the cheapest data quality tool in Odoo. A Selection field with five well named values produces reports that group cleanly, kanban columns that mean something, and automations that fire on predictable states. Free text in the same place produces none of that.

The decision that matters is not the widget, it is the value list. Keep it short enough that users never scroll past the choice they need, and resist encoding two dimensions into one list. When you see values like Urgent - Electrical and Urgent - Plumbing, that is two fields pretending to be one, and every report built on it will need untangling later.

The many2one mode earns its keep on configuration style relations: a company's three warehouses, four approval levels, a fixed set of rate cards. Users get a tap friendly closed list, and administrators keep the values as real records they can rename and archive without a developer.

Setting it up in Odoo Studio (no code)

Odoo Studio (Enterprise) covers this field end to end.

  1. Open the form you want to change and click Studio.

  2. Drag Selection from the Add a field panel onto the form. Studio prompts you for the list of values, one per line.

  3. In Properties, the Widget defaults to Selection, which is this dropdown. From the same dropdown you can switch the display to Badge, Badges, Radio, Priority or Status Bar without touching the stored values.

  4. To change the choices later, select the field and click Edit Values. Renaming a value relabels it everywhere. Deleting one does not clean up records that already store it, which matters below.

Tip: enable developer mode before adding the field so you can set a sane technical name. Reports, automations and integrations will reference it forever.

What Studio cannot do here

Studio manages the value list and the widget switch, and its general properties cover placeholders and conditional visibility. What it does not reach:

Filtering choices per view. Showing a different subset of values on different forms of the same model is what filterable_selection and dynamic_selection exist for, and wiring those is view level work.

Reacting to another field. Making the available choices depend on a second field on the record needs one of the filtering widgets or a developer built domain, not Studio.

Cleaning up removed values. Studio will happily delete a selection value that thousands of records still store. The stored strings stay behind, and in Odoo 19 they break the display, as covered in the deep dive. Plan a data migration whenever a value is retired. If that is on your roadmap, our Odoo customization team does this cleanup routinely.

Supported options in Odoo 19

Verified against selection_field.js in the Odoo 19.0 web module. The widget declares exactly one option, and the honest finding is that it does not consume it.

OptionTypeWhat it does
placeholder_fieldfield nameDeclared in supportedOptions as a Dynamic Placeholder hook for char fields, which is why Studio offers it, but extractProps never reads it, so setting it has no effect on this widget. Use the placeholder attribute instead.(since Odoo 19.0)

The one declared option is dead code in the widget. placeholder_field appears in supportedOptions, which is what makes Studio show a Dynamic Placeholder setting, but the widget's extractProps never reads it. Only the static placeholder attribute reaches the component. If you need a hint text on a selection dropdown, set placeholder="..." on the field node.

Working examples

Default dropdown on a selection field

<field name="state"/>
<!-- identical to -->
<field name="state" widget="selection"/>

Placeholder text while empty

<field name="priority_level"
       widget="selection"
       placeholder="Choose a level..."/>

A many2one as a closed dropdown

<field name="warehouse_id"
       widget="selection"
       domain="[('company_id', '=', company_id)]"/>

The domain is applied inside the name_search call, so users only ever see permitted rows. Because the widget offers no create path, this doubles as a soft lockdown of the relation.

Under the hood: one dropdown, two engines

The many2one mode is one cached query. The widget calls name_search once with an empty term plus your domain, and the ORM's default name_search limit of 100 records applies. There is no Search More and no paging, so a relation with hundreds of rows silently shows an incomplete list. Past a few dozen records, use a real many2one instead.

Kanban cards save instantly. extractProps hardcodes autosave to true when the view type is kanban, so changing the dropdown on a card writes the record immediately, with no Save step. In form views the same widget participates in the normal dirty record flow.

Choices with an empty label are hidden. The options getter filters out any selection entry whose label is an empty string. Developers sometimes use that to keep a legacy value storable but not offerable.

Removed values break the readonly display in 19. The label lookup does this.options.find(...)[1] with no guard, so a record holding a value that no longer exists in the selection throws a TypeError when the field renders its current label. This is the crash behind "the form went blank after we removed an old status." The Odoo 20 branch guards the lookup and shows the orphaned value as a grayed out, unselectable choice instead.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Kanban autosave removed and orphaned values render as disabled choices on the development branch. Details below.
Odoo 19.0VerifiedVerified against the shipped source. SelectMenu rendering with the mobile bottom sheet.
Odoo 18.0VerifiedSame XML. Rendered with the browser native select, no placeholder_field declaration, and false valued choices were also hidden.

Upgrade note for 18 to 19. Your XML keeps working, but the rendering changed from the browser's native select element to Odoo's SelectMenu, which brings the mobile bottom sheet and consistent styling. Two subtle differences travel with it: Odoo 18 also hid choices whose value is false, while 19 only hides empty labels, and the placeholder_field declaration only exists from 19.0.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The notes below are read from the public development branch, which is unstable and can change until feature freeze. We re-verify this page against the shipped release.

The kanban instant save disappears. The autosave prop and its kanban special case are removed on master. Dropdown changes on cards go through the standard update flow like any other edit, so flows that relied on the immediate write need review.

Orphaned values stop crashing. A stored value missing from the selection renders as a disabled, grayed out choice labeled with the raw value, fixing the Odoo 19 TypeError described above.

Offline resilience for many2one mode. The name_search call catches connection loss and falls back to displaying the current value instead of erroring.

The card rename reaches this widget. The view type check for the readonly passthrough now tests card instead of kanban, and the bottom sheet triggers on any touch device rather than only small screens.

Planning a jump to 20 when it lands? Our Odoo migration team tracks these branch changes so your views do not have to.

Common problems and fixes

SymptomCause and fix
Form errors or the field renders blank after removing a selection valueA record still stores the removed value, and the 19.0 label lookup has no guard for values missing from the selection. Restore the value or migrate stored data to a live value. Odoo 20 will degrade gracefully instead.
placeholder_field is set but nothing showsThe option is declared but never consumed by this widget. Use the static placeholder attribute on the field node.
A choice is missing from the dropdownSelection entries with an empty label are filtered out, or a domain excludes the row in many2one mode. Give the value a label, or test the field without its domain.
Many2one mode does not list all recordsThe single name_search call is capped at the ORM default of 100 results. Narrow the domain, or switch to the full many2one widget for large relations.
Changing the value on a kanban card saved the record immediatelyKanban view type hardcodes autosave to true in 19. Expected behavior. Move the edit to the form view if review before save matters.
Users can create new entries from the dropdownThey are not using this widget. The selection widget has no create path. Check the view. The field is likely rendering as a default many2one.

Selection field vs the alternatives

WidgetBest forKey difference
selectionSingle choice from a short, stable listClosed dropdown, no creation, one cached query in many2one mode
radioThree to five options users should see at onceRenders every choice as radio buttons, no dropdown
selection_badgeFast toggling between a few valuesAll values shown as clickable badges
statusbarValues that represent a workflow progressionArrow bar in the form header, click to advance
priorityImportance or rating scalesStars instead of labels, saves on click

The rule of thumb: keep the plain dropdown whenever the list is longer than a glance. Switch to radio or badges only when seeing every option at once genuinely helps the decision, and reach for statusbar when the values describe a progression rather than a category.

Frequently asked questions

Do I need to set widget="selection" on a selection field?+
No. It is the default renderer for every selection field, so a bare <field name="state"/> already uses it. You only write it explicitly to force a many2one to render as a closed dropdown.
Can I use the selection widget on a many2one field?+
Yes, that is a supported type. The widget loads matching records with one name_search call, honoring the field's domain, and renders them as fixed choices with no create option and no record opening. Keep it to small relations, because results are capped at the ORM default of 100.
How do I add a selection dropdown without a developer?+
In Odoo Studio, drag a Selection field onto the form and type the values. The dropdown widget is the default. Studio's Edit Values button manages the list afterward, but retiring a value that records already store needs a data cleanup, which is developer territory.
Why does my dropdown show no placeholder?+
Most likely the placeholder was configured through the placeholder_field option, which the widget declares but never reads in Odoo 19. Set the plain placeholder attribute on the field instead.
Does changing a selection on a kanban card save immediately?+
Yes in Odoo 19. The widget turns on autosave when it renders inside a kanban view, so the record is written the moment a new value is picked. The development branch for Odoo 20 removes this special case.
How do I show different selection values on different forms?+
Not with this widget. Use filterable_selection with its whitelist and blacklist options, or dynamic_selection, both of which exist for exactly that. The plain selection widget always offers the full value list.
What happens to records holding a deleted selection value?+
The stored string stays in the database. In Odoo 19 the widget crashes when rendering that value's label, so the field or form can appear broken. The Odoo 20 branch shows the orphan as a grayed out choice instead. Either way, plan a migration of stored values whenever the list shrinks.
Is the selection widget different on mobile?+
Yes. Since Odoo 19 replaced the native select with the SelectMenu component, small touch screens get a bottom sheet picker instead of a dropdown. The development branch extends that to every touch device.

Selection lists that fight your process?

Values nobody can retire, dropdowns that should depend on another field, statuses that need to differ per team: selection problems look small and quietly poison reporting. We untangle value lists, wire filtered and dynamic selections, and migrate the stored data so nothing breaks on the way.

Book a free consultation

How this page was produced

Every statement on this page was read from the Odoo 19.0 source file selection_field.js in the web module, including supportedOptions, extractProps and the option filtering logic, and the file was diffed against the 18.0 branch and the public development branch for the version notes. The Studio steps follow the official Studio fields documentation for 19.0. Where the source contradicts expectations, such as the unread placeholder_field option, we say so plainly. Spotted something we missed? Tell us and we will correct the page.