Skip to main content
iVentureTeam

selection_badge_with_filter

In Odoo 19 this widget shows a selection as badges filtered by another field's value. In Odoo 20 the same registration name belongs to a completely different widget, so the same XML does something else.

September 18, 2026Updated September 18, 20265 min read
Technical nameselection_badge_with_filter
Field typesselection
Viewsform
Moduleweb in Odoo 19. In Odoo 20 the same name is registered by hr_holidays instead.
Used in core1 use in Odoo 19, on the state field in odoo/addons/base/views/ir_actions_views.xml. That field uses badges_selection in Odoo 20.
VersionsOdoo 19.0, Odoo 20.0
No-code setupNo. There is no Studio entry, and the required option is not exposed anywhere.
Alternativesselection_badge, statusbar, selection, radio

What the selection_badge_with_filter widget does

This widget extends selection_badge and overrides one getter. Instead of returning every value in the selection, it returns only those that appear in another field on the same record:

get options() {
    const allowedSelection = this.props.record.data[this.props.allowedSelectionField];
    return super.options.filter(([value, _]) => allowedSelection.includes(value));
}

That companion field is named by the allowed_selection_field option. It is typically a computed field that works out which states are reachable from where the record currently is.

Everything else, including the badge rendering and the size option, comes from selection_badge unchanged.

What this means for your team

This solves a real workflow problem. A status field may have eight values, but from where a record sits today only three are legal. Showing all eight invites a user to pick an invalid one and then meet a server error.

Filtering at the widget means users only ever see the transitions that are allowed right now. The rules stay in Python, where they belong, and the interface simply reflects them.

If you are running Odoo 19 and using this pattern, read the Odoo 20 section before you upgrade. The behavior does not merely change; the name points at a different widget.

Supported options in Odoo 19

One inherited option and one required option that Odoo never declares. The undocumented one is not optional: the component's props declare it as a plain String with no optional flag, so omitting it fails prop validation rather than degrading.

OptionTypeWhat it does
allowed_selection_fieldfield name<strong>Required, and not declared in supportedOptions.</strong> Names another field on the record holding the list of selection keys to show. The component declares the matching prop as a non-optional String, so omitting it fails prop validation. The named field must be present in the view.
sizeselectionBadge size, one of sm, md or lg. Inherited from the selection_badge descriptor rather than declared here. Odoo's own view used sm, and dropped it when migrating to badges_selection in Odoo 20.(default: md)

allowed_selection_field does not appear in supportedOptions, so Studio will never offer it and no options helper will suggest it. It is read in extractProps and required by the component. This is the single most important thing to know about this widget, and it is documented nowhere in Odoo.

Working examples

The standard Odoo 19 use, on the server action state field:

<field name="allowed_states" invisible="1"/>
<field name="state" widget="selection_badge_with_filter"
       options="{'size': 'sm', 'allowed_selection_field': 'allowed_states'}"/>

The companion field must be in the view and must hold a list of selection keys. The Odoo 20 equivalent of the same field:

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

The same widget name means something else in Odoo 20

This is the most consequential finding on this page, and it is the kind of change that does not show up in a release note.

In Odoo 19, selection_badge_with_filter is registered in the web module. It is generic: give it any selection field and any companion field holding allowed values, and it filters.

In Odoo 20, the registration key is gone from web and reappears in hr_holidays, attached to a different class built on a different base widget:

export class HrHolidaysBadgeSelectionWithFilterField extends BadgesSelectionField {
    get options() {
        const { name, record } = this.props;
        const forceFullDuration = record.context?.force_full_duration;
        const isHalfDay = record.data.work_entry_type_request_unit === "half_day";
        const allOptions = super.options;
        if (forceFullDuration && name === "request_duration" && !isHalfDay) {
            return allOptions.filter(([value]) => value === "full");
        }
        return allOptions;
    }
}

It no longer reads allowed_selection_field at all. Its filtering is hardcoded to leave requests: a context flag, a field named request_duration, and a half-day check.

So a custom view carrying the Odoo 19 XML will, after an upgrade, resolve to a widget that ignores your option and applies unrelated logic. If hr_holidays is installed, you get the leave widget. If it is not, the registration does not exist at all and the field falls back. Either way, the filtering you built stops working, and nothing errors to tell you.

Odoo migrated its own use to badges_selection, and that widget reads allowed_selection_field in its extractProps, still without declaring it. The size option was dropped from the standard view in the process. That migration path is the one to follow.

Version compatibility

VersionStatusNotes
Odoo 19.0VerifiedGeneric filtering widget in the web module. Verified against the shipped 19.0 source.
Odoo 20.0Renamed / replacedName reused by an unrelated hr_holidays widget. Migrate to badges_selection.

This is a rename in the worst direction: the name survives and the meaning does not.

What is changing in Odoo 20

Treat this as a breaking change even though nothing errors.

The generic widget is gone from web. The registration name selection_badge_with_filter now belongs to an hr_holidays widget with hardcoded leave-duration logic that ignores allowed_selection_field. The supported type declaration changes too, since it inherits from badges_selection rather than badge_selection.

Odoo's own view moved to widget="badges_selection" with options="{'allowed_selection_field': 'allowed_states'}" and dropped size. Do the same in your custom views as part of the upgrade, and check every one of them, because a search for the widget name will still find matches that now mean something different.

Common problems and fixes

SymptomCause and fix
Prop validation fails and the field does not renderallowed_selection_field was not provided. The component declares it as a non-optional String. Add options="{'allowed_selection_field': 'your_field'}" and make sure that field is in the view.
No badges render at allThe companion field is empty or not loaded, so the filter matches nothing. Add the companion field to the view, invisible if needed, and check its computed value.
After upgrading to Odoo 20 the filtering stopped workingThe registration name now belongs to an hr_holidays widget that ignores allowed_selection_field. Switch to widget="badges_selection", which reads the same option. Drop the size option, as Odoo did.
After upgrading, the field renders as a plain selectionhr_holidays is not installed, so the Odoo 20 registration does not exist and Odoo falls back to the field type. Switch to badges_selection. Do not install hr_holidays to get the widget back; it is not the same widget.

Selection_badge_with_filter widget vs the alternatives

WidgetBest forKey difference
selection_badge_with_filterShowing only the legal next values of a status fieldFilters by another field, via an option Odoo never declares
selection_badgeBadges with no filteringShows every value in the selection
statusbarA pipeline shown across the top of a formDifferent layout, and filtering is done with statusbar_visible
selectionA plain dropdownNo badges, and filtering needs a domain or dynamic selection
radioA short list shown as radio buttonsAll values visible at once, no filtering

On Odoo 20, badges_selection is the direct replacement and reads the same undocumented option. On Odoo 19, if the filtering is not worth the undeclared dependency, a plain selection or statusbar with a domain or an invisible rule on individual buttons gets you part of the way, at the cost of more XML.

Frequently asked questions

How do I show only some values of an Odoo selection field as badges?+
In Odoo 19, use widget="selection_badge_with_filter" with options="{'allowed_selection_field': 'your_field'}", where that field holds the allowed keys. In Odoo 20, use badges_selection with the same option.
Why does selection_badge_with_filter fail to render?+
Almost always because allowed_selection_field is missing. The option is required but is not declared in the widget's supported options, and the component's prop is non-optional, so omitting it fails validation rather than degrading.
Does selection_badge_with_filter still work in Odoo 20?+
No, not as the same widget. The registration name was reused by an unrelated hr_holidays widget with hardcoded leave-duration logic that ignores allowed_selection_field. Migrate to badges_selection, which is what Odoo's own view now uses.
What replaced selection_badge_with_filter in Odoo 20?+
badges_selection. Odoo changed its own server action view to widget="badges_selection" with options="{'allowed_selection_field': 'allowed_states'}" and dropped the size option.

Upgrading to Odoo 20 with custom widgets in your views?

This widget keeps its name and changes its meaning, which is the kind of break no upgrade script catches and no error message announces. We diff your views against the 20.0 branch and hand you the list of what silently changes.

Get an upgrade audit

How this page was produced

Verified by reading addons/web/static/src/views/fields/badge_selection_with_filter/badge_selection_field_with_filter.js on the 19.0 branch of a local clone of the official Odoo repository, including the non-optional allowedSelectionField prop declaration and the extractProps that reads the undeclared option. The Odoo 20 replacement was read at addons/hr_holidays/static/src/components/selection_badge_with_filter/selection_badge_with_filter.js on the 20.0 branch and is quoted above. The migration of the standard view was confirmed by comparing odoo/addons/base/views/ir_actions_views.xml on both branches. Corrections welcome via our contact page.