Skip to main content
iVentureTeam

radio_selection_with_filter

Radio buttons that show only the choices this record is actually allowed to make. Small idea, and in Odoo 19 it changed contract in a way that silently breaks Odoo 18 views.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated August 27, 20266 min read
Odoo 19 survey form showing survey type radio buttons filtered by the radio_selection_with_filter widget.
Technical nameradio_selection_with_filter
Field typesselection
Viewsform
Modulesurvey, though nothing in the widget is survey-specific
Used in core1 occurrence, the survey type selector in survey
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupNo. Studio can set a Radio widget but cannot pass the allowed_selection_field option
Alternativesradio, selection, selection_badge_icons, image_radio

What the filtered radio field does

A selection field offers every value the model declares, always. That is usually right, and occasionally wrong: some choices only make sense for some records. A survey that already has answers cannot become a live session; a plan on a trial subscription cannot be the enterprise tier. Making the illegal choice visible and then rejecting it with an error is a poor experience.

This widget takes the ordinary radio rendering and filters it. It reads a second field on the same record, expects it to contain a collection of permitted values, and renders only the radio options whose value appears in that collection. Everything else disappears from the form.

Because it reads the allow-list from a field rather than from something fixed at render time, it is reactive. If the permitted set is a computed field, the visible radios update the moment the record changes in a way that changes the computation, without a page reload.

What this means for your team

Hiding an impossible option is a better experience than validating it after the fact, and it removes a whole class of support question: why does Odoo let me pick this and then refuse it? On a configuration screen shown to non-experts, that difference is worth more than it looks.

The design decision worth thinking about is whether hiding is honest. A choice that disappears without explanation can read as a bug or as a missing feature. If the reason matters commercially, for example a tier the customer could unlock, hiding it entirely is the wrong pattern and a disabled option with a tooltip is better. Core uses this widget on survey type, where the constraints are structural rather than commercial.

The other point for anyone maintaining an Odoo 18 database: this widget changed how it is configured in Odoo 19. Views that were fine before will need editing, and nothing about the failure points at the widget, so it is worth checking during upgrade preparation rather than after go-live.

Supported options in Odoo 19

One option is declared by the widget itself; horizontal comes from the base radio widget and works normally, because the widget keeps the base template. Read from radio_selection_field_with_filter.js and radio_field.js, Odoo 19.0.

OptionTypeWhat it does
allowed_selection_fieldstring (field name)Technical name of the field holding the permitted selection keys. Read live from the record on every render, so a computed field makes the radio list reactive. Required: there is no unfiltered fallback.(since Odoo 19.0)
horizontalbooleanInherited from the radio widget. Lays the radios out in a row instead of a column. Core passes it in the survey form.(default: false)

The field named by allowed_selection_field must be loaded in the view, and it must contain something with an includes method, which in practice means a list of selection keys. The prop is declared as required, so omitting the option is a props error rather than a silent pass-through, and the filter itself would fail as soon as it tried to read a field with no name.

Working examples

The core usage

<field name="allowed_survey_types" invisible="True"/>
<field name="survey_type" widget="radio_selection_with_filter"
       options="{'horizontal': True,
                  'allowed_selection_field': 'allowed_survey_types'}"
       invisible="not allowed_survey_types"/>

The allow-list field is loaded invisibly, and the whole radio group is hidden when nothing is allowed at all.

Vertical layout

<field name="tier" widget="radio_selection_with_filter"
       options="{'allowed_selection_field': 'allowed_tiers'}"/>

Without horizontal the base widget stacks the radios, exactly as the plain radio widget does.

What an Odoo 18 view looked like

<!-- Odoo 18 only: the allow-list came from context -->
<field name="survey_type" widget="radio_selection_with_filter"
       context="{'allowed_selection': ['survey', 'assessment']}"/>

On Odoo 19 this renders nothing useful: the context key is no longer read, and the required option is absent.

The Odoo 18 to 19 contract change

The class is fifteen lines: it extends RadioField, declares one extra prop, and overrides the items getter to filter the parent's list against the values held in the named field. Everything else, the rendering, the change handling, the layout option, belongs to the base radio widget.

Two deliberate narrowings sit in the descriptor. supportedTypes is set to ["selection"], dropping the many2one support the base radio widget has, which is consistent with the filter reading plain values. And the extractor spreads the base extractor before adding its own prop, so horizontal survives intact.

The version-to-version change is the part worth planning around. In Odoo 18 the prop was an array called allowed_selection, pulled from the field's context, and the filter compared against that fixed array. In Odoo 19 the prop became the name of a field, and the filter reads record.data[thatName] at render time. The behavior gained is reactivity; the cost is that every existing view has to change.

The failure mode is not friendly either. Without the option the required prop is missing, and if props validation is not active the filter reads record.data[undefined], which is undefined, and calling includes on it throws. Either way the form stops rendering rather than falling back to the unfiltered list.

Version compatibility

VersionStatusNotes
Odoo 20.0Partial / changedNot released. The widget survives, but core drops its only usage in favor of the badge-style selection widget.
Odoo 19.0VerifiedVerified against the shipped source. The allow-list is read from a field named by allowed_selection_field.
Odoo 18.0Partial / changedFirst version, different contract: the allow-list was a fixed array in the context key allowed_selection.
Odoo 17.0Not availableWidget does not exist.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. This is the one widget in this group that genuinely needs an XML edit on upgrade. Search inherited views for radio_selection_with_filter and convert any context="{'allowed_selection': [...]}" into options="{'allowed_selection_field': 'some_field'}", adding that field to the model if it does not exist. A computed non-stored selection-key list is the usual shape.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The development branch is unstable and this can still change; we re-verify the page after release.

The widget survives, its usage does not. The file is still registered on the development branch, with only the Owl props migration applied. But core's single usage moves away: the survey form now renders survey_type with the badge-style selection widget, passing the same allowed_selection_field option plus an icon mapping. That leaves this widget with no usages in core at all, which historically is how a widget gets deprecated.

If you use it, nothing breaks in Odoo 20. It is worth knowing that the maintained path is moving toward the badge widget.

Common problems and fixes

SymptomCause and fix
The form breaks after upgrading from Odoo 18The Odoo 18 context key allowed_selection is no longer read, so the required option is missing. Replace the context with options="{'allowed_selection_field': 'your_field'}" and load that field in the view.
No radio buttons at allThe allow-list field is empty or not loaded in the view. Add the field invisibly and confirm it returns a non-empty list of selection keys.
An error about includes not being a functionThe named field holds something other than a list, for example a char or a boolean. Make the field return a list of selection keys, typically a computed non-stored field.
The widget refuses a many2one fieldThis widget narrows supportedTypes to selection only, unlike the base radio widget. Use the plain radio widget for many2one fields.
horizontal is ignoredUsually a typo, since the option is inherited and does work here. Check the options dictionary syntax; the value must be True, not a string.
A previously chosen value vanished from the radiosThe allow-list no longer contains it, and the filter removes it from the rendered list. Expected. Show the stored value elsewhere if users need to see what they had.

Filtered radio field vs the alternatives

WidgetBest forKey difference
radio_selection_with_filterSelection fields where the legal choices depend on the recordFilters the radio list against a live allow-list field instead of showing every declared value
radioA short list of choices, all always availableNo filtering, and it supports many2one fields as well as selection
selectionLonger choice lists in a dropdownDropdown rendering, no per-record filtering
selection_badge_iconsChoices shown as icon badgesIcon-driven presentation for many2one fields, no allow-list filtering
image_radioChoices that are best recognized visuallyRenders images instead of labels, again with no filtering

Choose by how permanent the restriction is. If the allowed set genuinely varies per record, this widget or the badge widget carrying the same option is the answer. If the restriction is really about permissions, groups on the field are stronger, because they cannot be bypassed by a crafted write. And if the choice set is long, radios are the wrong control regardless of filtering.

Frequently asked questions

How does radio_selection_with_filter decide which choices to show?+
It reads the field named by allowed_selection_field on the same record and keeps only the radio options whose value appears in it. Because the read happens at render time, a computed allow-list makes the visible choices update live.
What changed between Odoo 18 and Odoo 19?+
The whole configuration. Odoo 18 took a fixed array from the context key allowed_selection; Odoo 19 takes a field name in the option allowed_selection_field. An Odoo 18 view moved across without editing will not work.
Can I use it on a many2one field?+
No. The descriptor narrows supported types to selection only, even though the base radio widget also accepts many2one.
Does the horizontal option work?+
Yes. It is inherited from the base radio widget and the template is unchanged, so it lays the radios out in a row. Core passes it in the survey form.
Is it going away in Odoo 20?+
The file is still registered on the development branch, but core moves its only usage to the badge-style selection widget, which accepts the same allowed_selection_field option. Nothing breaks, but the maintained path is clearly moving.

Users choosing options your process cannot honor?

Rules that live only in a validation message are rules people learn by failing. We rebuild those constraints into the interface itself, filtered choices, honest defaults and clear reasons, as part of Odoo customization on 16 through 19.

Book a free consultation

How this page was produced

The option, the narrowed supported types, the inherited layout option and the filter implementation were read from radio_selection_field_with_filter.js and radio_field.js on the Odoo 19.0 branch, with the usage taken from survey/views/survey_survey_views.xml. The Odoo 18 contract was read from the same file on the 18.0 branch, and the Odoo 20 notes from the development branch, including the replacement of the core usage. Spotted an error? Tell us and we will correct the page.