Skip to main content
iVentureTeam

selection_badge_icons

The activity scheduling dialog in Odoo 19 picks the activity type from icon-labeled badges. That row of buttons is selection_badge_icons, a many2one-only twist on selection_badge.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 24, 2026Updated August 24, 20266 min read
Technical nameselection_badge_icons
Field typesmany2one
Viewsform (activity dialogs)
Modulemail, shipped with every Odoo database
Used in core3 occurrences in the mail module, all on activity_type_id in activity dialogs
VersionsOdoo 19.0
No-code setupNo. XML only; Studio does not expose this widget
Alternativesselection_badge, radio, priority

What the icon badges widget does

Odoo 19 redesigned the Schedule Activity dialog, and the activity type selector became a row of badges, each carrying the type's icon: an envelope for Email, a phone for Call, a calendar for Meeting. The widget behind it is selection_badge_icons, registered by the mail module as a subclass of the core selection_badge widget.

Where the parent renders text-only badges for selection or many2one fields, this one is many2one-only and prepends an icon to every badge. The icon comes from a field on the related model, named through the iconField attribute; in core that is the icon char column on mail.activity.type, holding FontAwesome class names such as fa-phone. Records with an empty icon get the defaultIcon fallback, fa-check unless you set one.

The widget loads its choices itself with a search_read on the related model, honoring the field's domain, and renders one badge per record. Clicking writes the many2one like any selection badge; the active choice is highlighted.

What this means for your team

Icon badges beat a dropdown when the choice is small, frequent and recognizable. Scheduling an activity is exactly that: the same four to eight types, chosen dozens of times a day, faster to hit as a labeled button than to open, scan and click in a dropdown. Icons carry recognition; regulars stop reading the labels.

The same pattern fits custom pickers: a delivery method with a truck and a store icon, a ticket channel with mail and phone icons, a machine type on a maintenance request. The requirements are only that the related model carries an icon column with FontAwesome class names and that the option list stays short, because every option renders as a button and a twenty-record model turns the form into a wall of badges.

One planning note: this widget is an Odoo 19 feature and the development branch already replaces it with a core badges family, so treat it as a one-version bridge if you are building on it heavily. The section on Odoo 20 below has the details.

Supported options in Odoo 19

Read from badge_selection_icons_field.js on the Odoo 19.0 branch. The two icon knobs are XML attributes on the field element, camelCase and easy to mistake for options; the one true option is inherited from the parent badge widget. Entries below say which is which.

OptionTypeWhat it does
iconFieldattribute (camelCase)Required. XML attribute naming the char field on the related model that stores each option's FontAwesome class. Omitting it fails props validation and breaks the view.(since Odoo 19.0)
defaultIconattribute (camelCase)Optional XML attribute. FontAwesome class used for options whose icon field is empty.(default: fa-check)(since Odoo 19.0)
sizeselection: sm, md, lgInherited from selection_badge. Renders the badges as small, medium or large buttons.(default: md)

iconField is required. It is declared as a non-optional prop, so omitting the attribute does not fall back gracefully, it fails the OWL props validation and the dialog breaks. Always ship iconField with the widget, and remember both attributes are camelCase: iconField, defaultIcon, written as plain XML attributes, not inside options="{}".

Working examples

The core pattern, from the activity dialog

<field name="activity_type_id" required="1"
       widget="selection_badge_icons" iconField="icon" nolabel="1"/>

Custom picker with a fallback icon and size

<field name="channel_id" widget="selection_badge_icons"
       iconField="icon" defaultIcon="fa-question-circle"
       options="{'size': 'sm'}"/>

The related model side is one char column holding FontAwesome classes:

icon = fields.Char(string="Icon")  # e.g. "fa-phone", "fa-envelope"

The name column, the fa prefix, and readonly

Three source-level details decide whether this widget works for a custom model.

It reads the literal name column. The option fetch requests exactly ["id", "name", iconField] from the related model. Models whose display name comes from _rec_name pointing elsewhere, or from a computed display_name, will render empty or wrong labels, because the widget never asks for display_name. The related model needs a real name field with the text you want on the badges.

The fa prefix is hardcoded. The template renders the icon as class="fa {icon}", so icon values must be FontAwesome class names like fa-truck. Odoo's newer oi- icon set or image fields will not render through this widget.

Readonly drops the icons. The readonly branch of the template prints the value as plain text, no badges, no icon. If a form shows the field conditionally readonly, expect the visual to change completely between states.

Also inherited from the parent: the empty-check treats false as empty, the field's domain filters which records become badges, and the whole option list loads eagerly, one more reason to keep the related model short.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentProvisional: deleted on the development branch, replaced by badges_many2one with related_icon_field. See below.
Odoo 19.0VerifiedIntroduced in 19.0 with the redesigned activity dialog; verified against the shipped source.
Odoo 18.0Not availableDoes not exist; the activity dialog used a plain selector.
Odoo 17.0Not availableDoes not exist.
Odoo 16.0Not availableDoes not exist.

Upgrade note. New in Odoo 19; there is nothing to migrate from earlier versions. Views written against it will need attention at the Odoo 20 upgrade, see below.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. What follows is read from the public development branch, which is unstable until release; we re-verify once it ships.

The widget is deleted on master. The whole badge_selection_icons directory is gone from the mail module, one release after it appeared. Its role passes to the new core badges family that replaces selection_badge: a rebuilt badges_selection for selection fields with an icon_mapping option, and a new badges_many2one whose related_icon_field option covers exactly what iconField does today, both with their own default-icon handling.

Practical consequence: an arch using widget="selection_badge_icons" will fall back to the plain many2one widget after the upgrade, silently losing the badge UI. The rewrite to badges_many2one with related_icon_field is small but must be done by hand, the kind of line-item an Odoo migration review catches before users notice. Support for 20 is provisional until release; we will re-verify and update this table.

Common problems and fixes

SymptomCause and fix
Dialog crashes with a props validation errorThe iconField attribute is missing; it is a required prop. Add iconField="icon" (or your icon column) to the field element.
Badges show but every icon is a check markThe icon field is empty on those records, so defaultIcon (fa-check) kicks in. Fill the icon column with FontAwesome classes, or set defaultIcon to something meaningful.
Badges render with no label textThe related model has no real name column; the widget fetches name literally, not display_name. Add or populate a name field on the related model.
Icons never render for oi- style classesThe template hardcodes the fa prefix, so only FontAwesome classes work. Use fa-* icon names in the icon column.
Field shows plain text with no badgesThe field is readonly; the readonly template drops the badge UI entirely. Expected behavior; make the field editable to get badges back.
Widget refuses a selection fieldsupportedTypes is many2one only, unlike the parent selection_badge. Use selection_badge for selection fields.

Icon badges widget vs the alternatives

WidgetBest forKey difference
selection_badge_iconsShort many2one choices picked constantly, like activity typesIcon-labeled badges fetched via search_read, many2one only
selection_badgeText-only badges on selection or many2one fieldsNo icons, broader type support, same click behavior
radioChoices that must look like a form, not buttonsRadio circles, optional horizontal layout, no icons
priorityRanked levels like priorityStars instead of badges, selection fields

Keep icon badges for short, recognizable choice sets a user hits constantly. The moment options need search, creation or more than a dozen entries, you are back in dropdown territory.

Frequently asked questions

What is the selection_badge_icons widget used for in Odoo 19?+
It renders a many2one as a row of clickable badges with FontAwesome icons, and core uses it for the activity type picker in the redesigned Schedule Activity dialog, reading each type's icon field via iconField="icon".
Why are iconField and defaultIcon not inside options?+
Because they are declared as component props extracted from XML attributes, not as widget options. Write them as attributes on the field element: iconField="icon" defaultIcon="fa-tag". Only size, inherited from selection_badge, goes in options.
Can I use selection_badge_icons on a selection field?+
No. It declares supportedTypes: ["many2one"] and its data loading is a search_read on the related model, which a selection field does not have. Use selection_badge for selections.
Where do the icons come from?+
From a char field on the related model holding a FontAwesome class per record, such as fa-phone. The widget requests that field by the name you pass in iconField and prepends it to each badge; empty values fall back to defaultIcon.
Does it work with models that use display_name?+
Only partially: the widget fetches the literal name column for the badge labels, never display_name. A related model without a real name field will show blank badges, which is the main constraint when reusing the widget on custom models.
Is selection_badge_icons available in Odoo 20?+
On the current development branch it is deleted, with the new core badges_many2one widget and its related_icon_field option taking over the use case. That is provisional until Odoo 20 ships in late September 2026; we re-verify this page against the release.

One-click pickers your users stop thinking about

We turn slow dropdowns into icon badge pickers where they earn their place, wire the icon columns behind them, and plan the rewrite to the Odoo 20 badges widgets before the upgrade forces it. UI polish in Odoo is cheap when someone has read the source first.

Improve my form UX

How this page was produced

Verified by reading badge_selection_icons_field.js and its QWeb template on the Odoo 19.0 branch, plus the parent badge_selection_field.js for the inherited option and empty-check, and by searching the development branch tree, where the directory no longer exists, for the Odoo 20 section. The required-prop behavior, the literal name column fetch and the hardcoded fa prefix are all read directly from the source. Core usage was confirmed in the mail activity view archs. Spotted an error? Tell us.