Skip to main content
iVentureTeam

selection_badge

When every option should be visible and one click away, selection_badge replaces the dropdown with a row of pills. It also hides three behaviors nobody expects: a self-clearing click, a text-only readonly mode, and a full reload of many2one options.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 12, 2026Updated August 12, 20266 min read
Odoo 19 form showing a selection rendered by selection_badge as pill buttons with the active option highlighted.
Studio nameBadges
Technical nameselection_badge
Field typesselection, many2one
Viewsform, list (list.selection_badge variant)
Also registered aslist.selection_badge (adds color_field); sibling widget selection_badge_with_filter in the same module
Moduleweb, present in every Odoo database
Used in core17 occurrences across 8 modules, including hr_skills, hr_recruitment_skills, mail, calendar, marketing_card, crm
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupYes for selection fields, via Odoo Studio (Enterprise); many2one usage is XML only
Alternativesradio, badge, label_selection, priority

What the Selection Badge widget does

selection_badge lays every possible value of a field out as a horizontal row of pill buttons. The current value gets the active highlight; picking a different value is one click, with no dropdown to open. Core uses it where choices are few and switching is frequent: skill levels in recruitment, meeting privacy in calendar.

It accepts two field types, and treats them differently. On a selection, the pills are the declared values, straight from the field definition. On a many2one, the widget fetches options with name_search on the related model, honoring the field's domain, and here is the catch read straight from the source: it fetches with an empty search term and no explicit limit, meaning all matching records become pills.

Two more behaviors from the source complete the picture. Clicking the active pill on a non-required selection clears the value back to empty. And in readonly contexts the widget does not render pills at all, just the current value as plain text.

What this means for your team

Dropdowns hide information; pills expose it. For the three-to-six option decisions your team makes hundreds of times a day, triage categories, priority buckets, skill levels, showing every option turns a two-click choose-and-scan into a single click. It also makes the option set self-documenting for new hires.

The clear-on-reclick behavior deserves a mention in your user onboarding: it is the fastest way to unset a value, and simultaneously the most common accidental data change with this widget. Required fields are immune, the source checks.

Know when to stop: pills consume horizontal space per option. Past roughly six options, or with long labels, the row wraps and the scan advantage dies; that is dropdown territory, or radio territory when vertical space is cheap.

Setting it up in Odoo Studio (no code)

Studio offers this widget for Selection fields under the name Badges.

  1. Open the form in Studio and select the Selection field.

  2. In the Properties tab, set Widget to Badges.

  3. Click Close to leave Studio.

The same choice appears for Priority-type selection fields, where Badges is listed among the interchangeable widgets.

What Studio cannot do here

Studio stops at selection fields: the docs list only Badge and Radio as alternative many2one widgets, so putting pills on a many2one is an XML edit. The size option and the list variant's color_field are likewise set by hand in the view XML.

Supported options in Odoo 19

Verified against badge_selection_field.js and list_badge_selection_field.js in the Odoo 19.0 web module. Both options are 19.0 additions; the 18.0 file has neither.

OptionTypeWhat it does
sizeselectionPill size: sm, md or lg, mapped to Bootstrap button size classes in edit mode. Default md.(default: md)(since Odoo 19.0)
color_fieldfield name<strong>Only on the list.selection_badge variant.</strong> Integer field holding a color index 0 to 11; readonly list rows render the badge in that color. Ignored on forms.(since Odoo 19.0)

color_field only exists on the list variant, and only acts in readonly rows, where it colors the badge from an integer field using the standard 0 to 11 palette. In editable list rows the widget falls back to the normal pill row. On forms the option is silently ignored.

Working examples

Selection as pills

<field name="level" widget="selection_badge"/>

Large pills for touch screens

<field name="level" widget="selection_badge"
       options="{'size': 'lg'}"/>

Many2one pills, domain limited

<field name="team_id" widget="selection_badge"
       domain="[('active', '=', True)]"/>

Every team matching the domain becomes a pill. Keep the domain tight; the fetch has no limit.

Colored badges in a list column

<field name="skill_level_id" widget="selection_badge"
       options="{'color_field': 'color'}"/>

In list views Odoo automatically picks the list.selection_badge variant, which reads the record's color integer for the badge color in readonly rows.

Three behaviors that generate support tickets

Readonly means text. The template's readonly branch renders the current value's label as a plain span, no pills, no colors (except the list variant's color_field case). Teams that chose pills for their looks are regularly surprised when the saved form shows plain text. If the goal is a colored state display, badge or label_selection is the right tool.

Many2one loads everything. The options come from a name_search with an empty term over the field's domain. Fifty records make fifty pills. There is no paging and no Search More; the widget is built for small referential models like skill levels or teams.

Clearing is a feature. onChange compares the clicked value with the current one; equal and not required means update to false. The same code path means clicking any pill writes through the standard record update, so dirty-state handling and onchanges behave exactly as with a dropdown.

The module also ships a sibling, selection_badge_with_filter, which takes an allowed_selection_field option and shows only the pills whose keys appear in another field's value, the badge cousin of dynamic_selection.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Replaced by badges_selection and badges_many2one on the development branch; see below.
Odoo 19.0VerifiedVerified against the shipped source, including both registered variants.
Odoo 18.0Partial / changedCore pill behavior only: no size, no color_field, no list variant, no with_filter sibling. Verified against the 18.0 source.

Upgrading from Odoo 18? The core pill behavior is unchanged, but everything around it is new in 19.0: the size option, the list.selection_badge variant with color_field, and the selection_badge_with_filter sibling all have no 18.0 equivalent.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The changes below are read from the public development branch and are not final until release.

This widget is being replaced. The file registering selection_badge is gone from the development branch. In its place: badges_selection, selection-only, with a new badge_limit option that folds excess options into a More dropdown, plus icon support and keyboard navigation (arrow keys, space to select, backspace to clear); and a separate badges_many2one widget for many2one fields with related_icon_field and default_icon options. The 19.0 size and color_field options have no counterpart in the new files, and selection_badge_with_filter moves from web into hr_holidays. As read today, XML using widget="selection_badge" would fall back to the default selection widget after upgrade unless an alias is added before release; we re-verify when Odoo 20 ships.

Common problems and fixes

SymptomCause and fix
Saved form shows plain text instead of pillsReadonly rendering is text by design; pills exist only in edit mode. Use badge or label_selection if you want a styled state display in readonly.
Value disappears after clickingClicking the active pill clears a non-required field. Expected behavior. Make the field required to prevent empty values, and mention the shortcut in training.
Form is slow and covered in pillsThe field is a many2one over a large model; every matching record was fetched as a pill. Tighten the field's domain or switch to a normal many2one; the widget is intended for small option sets.
color_field does nothingThe option lives on the list variant only and acts only in readonly rows. Use it in list views; on forms combine the field with the badge widget instead.
Pills wrap over several linesToo many options or labels too long for the container width. Shorten labels, reduce options, or accept the dropdown of the plain selection widget.

Selection Badge widget vs the alternatives

WidgetBest forKey difference
selection_badgeSmall option sets switched frequentlyEvery option is a visible pill; click active to clear; text-only in readonly
radioAll options visible, arranged verticallyRadio buttons with labels, horizontal option available, no clear-on-reclick
badgeReadonly state display with decoration colorsDisplay-only widget; never editable
label_selectionColored status labels in list viewsDisplay-only, colors mapped per value via the classes option
prioritySelections that mean a scaleStars instead of pills, saves on click

Pills are for choosing; badges are for showing. If users click it, stay here (or radio for vertical lists and priority for star scales). If users only read it, badge and label_selection render state without implying it is editable.

Frequently asked questions

How do I show a selection as buttons in Odoo?+
Set widget="selection_badge" in the view XML, or pick the Badges widget on a Selection field in Studio. Every declared value renders as a clickable pill.
Why does clicking the selected pill empty the field?+
The source clears the value when the clicked pill is already active and the field is not required. It is the intended way to unset the field; required fields ignore it.
Why do pills disappear when the record is saved?+
They do not disappear, the form switched to readonly, where this widget renders the value as plain text. Only edit mode shows pills.
Can I use it on many2one fields?+
Yes in XML (supportedTypes includes many2one), with one caution: all records matching the domain are fetched as pills via name_search, with no limit. Studio does not offer it for many2one.
How do I get colored badges in a list view?+
Use the list variant's option: options="{'color_field': 'color'}" where color is an integer field with values 0 to 11. The color shows in readonly rows; editable rows show normal pills.
What is selection_badge_with_filter?+
A sibling widget in the same module that adds an allowed_selection_field option and displays only the pills whose keys are listed in that field, per record. hr_holidays uses it for leave request units.

Are your forms fighting your users?

Widget choice is UX strategy in miniature: pills for fast switching, stars for scales, badges for state. We redesign Odoo screens field by field, the right widget, the right defaults, the right required flags, until data entry stops being the slowest part of your process.

Book a free consultation

How this page was produced

This page was verified by reading badge_selection_field.js, list_badge_selection_field.js, badge_selection_field_with_filter.js and the QWeb template in the Odoo 19.0 web module, including onChange, the name_search fetch and the readonly branch. The 18.0 branch was compared (none of the 19.0 extras exist there), and the development branch was searched for the replacement files, where the badges_selection and badges_many2one descriptors were read in full. Spotted an error or a version difference? Tell us and we will correct the page.