Skip to main content
iVentureTeam

badges_selection

New in Odoo 20 and the replacement for selection_badge. It declares a single option and quietly reads four more, two of which do conditional choice filtering with no Python at all.

September 18, 2026Updated September 18, 20264 min read
Technical namebadges_selection
Field typesselection
Viewsform, list
Moduleweb, present in every Odoo 20 database
Used in core26 uses across Odoo 20 Community and Enterprise views, excluding tests. Does not exist in Odoo 19.
VersionsOdoo 20.0
No-code setupPartly. Studio will offer only badge_limit, because it is the sole declared option.
Alternativesbadges_many2one, selection_badge, statusbar, radio

What the badges_selection widget does

badges_selection renders a selection field as a row of clickable badges instead of a dropdown, so every choice is visible and selecting one is a single click.

It is built on a shared BaseBadgesField that it has in common with badges_many2one, which is why the two behave identically apart from where their choices come from.

The interesting part is the gap between what it declares and what it reads. The descriptor lists one supported option. Its extractProps reads five values from the options dictionary and a sixth from the field's required state.

What this means for your team

Badges suit a short list that people set often: a stage, a priority, an approval state. A dropdown hides the options behind a click; badges put them on the screen and halve the interaction.

The filtering options are the ones worth knowing about, because they solve a problem most teams currently solve with Python. If a record's legal next states depend on where it is now, you usually compute that server-side and then fight the interface to reflect it. Here you compute the allowed list into a field and name that field in the widget. The badges follow.

Supported options in Odoo 20

One option is declared and will appear in Studio. Four more are read from the options dictionary and appear nowhere. All five work.

OptionTypeWhat it does
badge_limitnumberDisplays a dropdown once the badge count is higher than this value. The only declared option, so the only one Studio will offer.(default: 0, meaning unlimited)(since Odoo 20.0)
allowed_selection_fieldfield name<strong>Undocumented.</strong> Names another field on the record holding the list of selection keys to show. Conditional choice filtering with no Python. This is where Odoo 19's selection_badge_with_filter behavior went.(since Odoo 20.0)
excluded_selection_fieldfield name<strong>Undocumented.</strong> The inverse of the above: names a field holding selection keys to hide. Useful when it is easier to compute what is forbidden than what is allowed.(since Odoo 20.0)
icon_mappingdictionary of value to icon class<strong>Undocumented.</strong> Maps each selection value to an icon class shown on its badge. Together with default_icon this replaces Odoo 19's separate selection_badge_icons widget.(since Odoo 20.0)
default_iconstring<strong>Undocumented.</strong> Fallback icon class for any value not covered by icon_mapping.(since Odoo 20.0)

Only badge_limit is in supportedOptions. The other four are read directly in extractProps, so no tooling will suggest them and no documentation mentions them. They are as real as the declared one, and two of them do the most useful thing this widget can do.

Working examples

Plain badges:

<field name="state" widget="badges_selection"/>

Showing only the states the record can legally move to. This is the pattern Odoo itself uses on server actions:

<field name="allowed_states" invisible="1"/>
<field name="state" widget="badges_selection"
       options="{'allowed_selection_field': 'allowed_states'}"/>

With icons, replacing the Odoo 19 selection_badge_icons widget:

<field name="state" widget="badges_selection"
       options="{'icon_mapping': {'draft': 'fa-pencil', 'done': 'fa-check'},
                 'default_icon': 'fa-circle-o', 'badge_limit': 5}"/>

Four options Odoo never declares

Here is the whole configuration surface, quoted from the source:

extractProps: ({ options }, dynamicInfo) => ({
    defaultIcon: options.default_icon,
    badgeLimit: options.badge_limit,
    canDeselect: !dynamicInfo.required,
    iconMapping: options.icon_mapping,
    allowedSelectionField: options.allowed_selection_field,
    excludedSelectionField: options.excluded_selection_field,
}),

Compare that against the declared list, which contains exactly one entry, badge_limit. Four options are read and never announced.

The two filtering options are the significant ones. Each names another field on the same record whose value is a list of selection keys, and the widget narrows the badges accordingly. That is conditional choice filtering driven entirely from a view attribute, where the usual approach is a dynamic selection method in Python.

This is also the migration path from Odoo 19. That version had a separate widget, selection_badge_with_filter, whose allowed_selection_field option was likewise undeclared. Odoo 20 removed the generic version of that widget, recycled its name for an unrelated hr_holidays widget, and moved its own use here. In ir_actions_views.xml the Odoo 19 line reads widget="selection_badge_with_filter" options="{'size': 'sm', 'allowed_selection_field': 'allowed_states'}" and the Odoo 20 line reads widget="badges_selection" options="{'allowed_selection_field': 'allowed_states'}". The size option did not survive.

One more behavior worth knowing: canDeselect is derived from the field's required state rather than from an option. A non-required field lets a user clear the value by clicking the active badge again. A required one does not. There is no way to override that from the view.

Version compatibility

VersionStatusNotes
Odoo 19.0Not availableDoes not exist. The nearest equivalents are selection_badge and selection_badge_icons.
Odoo 20.0VerifiedIntroduced in Odoo 20. Verified against the shipped 20.0 source.

This widget does not exist before Odoo 20.

What is changing in Odoo 20

Introduced in Odoo 20, replacing selection_badge from Odoo 19, which had 31 uses and is removed.

It also absorbs two widgets that were separate in Odoo 19. selection_badge_icons, which existed only to add icons, is replaced by the icon_mapping and default_icon options here. And the filtering behavior of selection_badge_with_filter moves here through allowed_selection_field.

Be careful with that last one. The name selection_badge_with_filter still exists in Odoo 20, but it now belongs to an unrelated hr_holidays widget with hardcoded leave-duration logic that ignores allowed_selection_field entirely. Migrating to badges_selection is the correct move; leaving the old widget name in place is not.

Common problems and fixes

SymptomCause and fix
Only badge_limit appears in StudioIt is the only declared option; the other four are read but never announced. Set the rest in the view XML. They work despite being undocumented.
No badges render at allallowed_selection_field points at a field that is empty or not loaded in the view, so the filter matches nothing. Add the companion field to the view, invisible if needed, and check its computed value.
A user cannot clear the valueDeselection is derived from the field's required state, not from an option. A required field cannot be cleared. Make the field non-required if clearing should be possible. There is no option to override this.
selection_badge_with_filter behaves strangely after upgradingIn Odoo 20 that name belongs to an unrelated hr_holidays widget that ignores allowed_selection_field. Migrate to badges_selection, which is what Odoo's own views now use.

Badges_selection widget vs the alternatives

WidgetBest forKey difference
badges_selectionA short selection set often, with choices that may depend on another fieldFilters choices from another field through an option Odoo never declares
badges_many2oneThe same badge interface for a many2oneChoices come from a related model rather than a selection list
selection_badgeBadges on Odoo 19Removed in Odoo 20
statusbarA pipeline across the top of a formDifferent layout, and filtering uses statusbar_visible
radioA short list as radio buttonsNo filtering and no icons

Use badges_many2one when the choices come from another model rather than a selection list; it is the same base component with a different source. Use statusbar when the values form a pipeline that belongs across the top of a form. Use a plain selection when the list is long enough that badges would wrap into a wall.

Frequently asked questions

How do I show only some options of a selection field in Odoo 20?+
Use widget="badges_selection" with options="{'allowed_selection_field': 'your_field'}", where that field holds the list of allowed selection keys. The option is real but undeclared, so Studio will not offer it.
What options does badges_selection support?+
It declares one, badge_limit, and reads four more that are undocumented: allowed_selection_field, excluded_selection_field, icon_mapping and default_icon. All five work.
What replaced selection_badge in Odoo 20?+
badges_selection. It also absorbs selection_badge_icons through the icon_mapping option, and takes over the filtering behavior that selection_badge_with_filter provided in Odoo 19.
Why can users not deselect a badge?+
Because deselection is derived from whether the field is required, not from an option. A required field cannot be cleared, and there is no way to override that from the view.

Workflow rules the interface does not reflect?

Most Odoo databases enforce which status a record can move to in Python and then let the form offer every option anyway. Odoo 20 can filter the choices from a field. We model the transitions properly and make the screen match them.

Talk to an Odoo consultant

How this page was produced

Verified by reading addons/web/static/src/views/fields/badges_selection/badges_selection_field.js on the 20.0 branch of a local clone of the official Odoo repository, with extractProps and the single-entry supportedOptions quoted above. The migration path was confirmed by diffing odoo/addons/base/views/ir_actions_views.xml between the 19.0 and 20.0 branches, and the recycled selection_badge_with_filter name by reading its Odoo 20 definition in addons/hr_holidays/. The usage count comes from scanning every non-test XML file in Community, Enterprise and odoo/addons. Corrections welcome via our contact page.