Skip to main content
iVentureTeam

lunch_is_favorite

Nine lines of code that exist for one reason: Odoo's lunch menu kanban is declared non-editable, and the favorite star still has to work.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated August 27, 20266 min read
Technical namelunch_is_favorite
Field typesboolean
Viewskanban, list, form
Modulelunch
Used in core1 occurrence, the lunch menu kanban card in lunch
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupNo. Studio cannot set this widget, and the behavior only matters on a non-editable view
Alternativesboolean_favorite, boolean_toggle, priority

What the lunch favorite field does

Odoo's lunch app shows today's menu as a grid of product cards. The grid is deliberately not editable: employees are ordering lunch, not maintaining a product catalog, so the kanban is declared with edit="0" and every field on the card is rendered read-only.

That creates a small conflict. Marking a dish as a favorite is one of the few things an employee should be able to do from that grid, and the standard favorite-star widget refuses to write when the view says read-only. lunch_is_favorite is the resolution: the same star, with its read-only decision taken from a different place.

Instead of asking the view whether this field is currently editable, it looks only at whether a readonly attribute was written on the field element in XML. In the lunch kanban there is none, so the star stays live even though everything around it is frozen.

What this means for your team

Favorites are a small feature with a measurable effect on adoption. If an employee can mark the dishes they order every week, ordering becomes two clicks instead of a scroll through a supplier's whole menu, and the app gets used. Blocking that on a read-only grid would have quietly removed the reason to open the app at all.

The generalizable point for custom Odoo work is the pattern rather than the widget. Read-only views are a blunt instrument: they lock the whole record when the intent is usually to lock the business data and leave the personal, per-user flags alone. A tiny widget that opts one field out is often the cleanest answer, far cleaner than making the whole view editable and then defending it with rules.

The security note belongs with it. Because the star ignores what the view says, whatever protects the underlying field has to live on the server: access rights, record rules or an override on write. The widget only decides what the interface offers, never what the database accepts.

Supported options in Odoo 19

The widget adds no options. Its descriptor spreads the favorite-star descriptor and replaces only extractProps, so the option below is inherited and works exactly as it does on the base widget. Read from lunch_is_favorite_field.js and boolean_favorite_field.js, Odoo 19.0.

OptionTypeWhat it does
autosavebooleanInherited from the favorite-star widget. When true, clicking the star saves the record immediately instead of leaving it dirty. Core relies on the default, because a kanban card has no save button.(default: true)

Read-only behaves differently here, and that is the entire widget. The base star reads the evaluated read-only state, which accounts for the view, the record and any readonly expression. This one reads the raw readonly attribute and coerces it with a boolean cast, so a non-empty attribute value of any kind, including the string 0, makes the star read-only, and the absence of the attribute makes it editable no matter what the surrounding view says.

Working examples

The core usage

<kanban js_class="lunch_kanban" create="0" edit="0">
  ...
  <field name="is_favorite" widget="lunch_is_favorite" nolabel="1"/>
</kanban>

edit="0" is the reason the widget exists. With the plain favorite widget the star would render and refuse to toggle.

Locking the star deliberately

<field name="is_favorite" widget="lunch_is_favorite"
       readonly="1"/>

A literal attribute is the only thing that locks it. Note that readonly="0" locks it too, because the attribute string is simply cast to a boolean.

Without immediate saving

<field name="is_favorite" widget="lunch_is_favorite"
       options="{'autosave': False}"/>

Inherited from the base star. On a kanban card this is rarely what you want, since there is no save button in sight.

One replaced prop, and the coercion it introduces

The file has no component class at all. It exports a descriptor that spreads booleanFavoriteField and overrides extractProps to call the base extractor and then replace one key: readonly: Boolean(fieldsInfo.attrs.readonly).

To see why that matters, look at what the base extractor writes: readonly: dynamicInfo.readonly. That is the evaluated state, the one that accounts for the view's edit="0", the record being locked, and any readonly expression on the field. The base star's update method returns early when that prop is true, so on the lunch kanban the star would render at the right state and simply never change.

Swapping the source of that prop for the static attribute cuts the star loose from the view's opinion. It also introduces the coercion quirk. attrs.readonly is the raw XML attribute, a string, and every non-empty string is truthy in JavaScript. readonly="0", which reads to a developer as not read-only, produces true. So does an expression such as readonly="state == 'done'", which is never evaluated here and simply locks the star permanently.

Everything else comes from the base widget: the star and outline-star icons, the Add to Favorites and Remove from Favorites labels, the list column width of 20 pixels when the field carries no label, and the autosave option that defaults to true and makes the click a direct write.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Byte-identical to Odoo 19 on the development branch.
Odoo 19.0VerifiedVerified against the shipped source. Identical to Odoo 18.
Odoo 18.0VerifiedFirst version. Same descriptor override.
Odoo 17.0Not availableWidget does not exist.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. The widget arrived in Odoo 18, and the Odoo 18, Odoo 19 and development-branch files are identical, so nothing needs attention on upgrade. On Odoo 17 and earlier the lunch kanban used a different arrangement; backporting the widget is trivial, since the whole file is nine lines.

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, so this may still change; we re-verify the page after release.

Byte-identical. The file has not been touched on the development branch, which is notable in a cycle that rewrote most field widgets onto the new Owl props syntax. This one survives untouched because it declares no component and no props of its own, only a descriptor override.

Worth watching indirectly: any change to the base favorite widget's readonly handling would flow straight through here, since that is the single line this widget replaces.

Common problems and fixes

SymptomCause and fix
The star is frozen even though there is no readonly expression in effectA readonly attribute is present on the field element. Its value is never evaluated, only cast to a boolean, so even readonly="0" locks it. Remove the readonly attribute entirely from the field element.
The star is clickable on a record the user should not touchIntended behavior. The widget ignores the evaluated read-only state. Enforce the restriction with access rights or a record rule; the interface is not the control point here.
Clicking the star does not persistautosave was turned off and the view has no save action. Remove 'autosave': False, or move the field to a view with a save button.
Missing widget error in the logThe lunch module is not installed in that database. Install lunch, or use the base boolean_favorite widget instead.
The star column is too narrow in a listThe base widget sets a 20 pixel column width when the field has no label. Give the column a label, or set a width on the list column.
The star does not appear at allThe field is not a boolean; supported types are inherited and limited to boolean. Point the widget at a boolean field.

Lunch favorite field vs the alternatives

WidgetBest forKey difference
lunch_is_favoriteA per-user favorite flag on a view that is deliberately not editableTakes its read-only state from the literal XML attribute instead of the evaluated view state
boolean_favoriteA favorite star on an ordinary editable viewHonors the evaluated read-only state, so it freezes with the rest of the view
boolean_toggleAn on/off setting rather than a personal favoriteSwitch styling and no star semantics
priorityRanking records by importanceStars representing a graded value, not a single boolean

If your view is editable, the plain boolean_favorite widget is the right choice and behaves predictably with readonly expressions. Reach for this pattern only when a per-user flag has to stay live on a view that is deliberately locked, and remember to enforce the real restriction on the server rather than in the interface.

Frequently asked questions

What does lunch_is_favorite change compared to boolean_favorite?+
Exactly one prop. The base widget takes its read-only state from the evaluated view state; this one takes it from the literal readonly attribute on the field element. Everything else, including the icons, labels and autosave, is inherited.
Why is the star still clickable on a non-editable kanban?+
That is the point of the widget. Odoo's lunch menu kanban is declared with edit="0", which would freeze the base star. Ignoring the evaluated state keeps favorites usable while the rest of the card stays locked.
Does readonly="0" work?+
No, and it is a trap. The attribute is not evaluated, it is cast to a boolean, and every non-empty string is truthy. Remove the attribute instead of setting it to zero.
Can I use it outside the lunch app?+
Yes, as long as the lunch module is installed, since that is where it is registered. Nothing in the nine lines is lunch-specific.
Is the field protected if the star ignores readonly?+
Only by the server. Access rights, record rules or a write override are what actually protect it; the widget decides what the interface offers, not what the database accepts.

Locked-down screens that still need one live control?

Read-only views are easy to declare and awkward to soften afterwards, and the usual workaround is to unlock far more than you meant to. We solve those cases precisely, one field at a time, as part of Odoo customization work on 16 through 19.

Book a free consultation

How this page was produced

The replaced prop and its coercion were read from lunch_is_favorite_field.js on the Odoo 19.0 branch, and the behavior it overrides from boolean_favorite_field.js in the same branch. The reason for the override was confirmed against the lunch menu kanban in lunch/views/lunch_product_views.xml, which declares edit="0". Version coverage comes from comparing the file across 16.0, 17.0, 18.0 and the development branch. Spotted an error? Tell us and we will correct the page.