Skip to main content
iVentureTeam

integer_update_flag

The numeric twin of boolean_update_flag: an integer input that also records whether a human, rather than a recalculation, moved the number. It has one sharp edge above 999.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated August 27, 20266 min read
Technical nameinteger_update_flag
Field typesinteger
Viewsform, list
Modulesurvey, though nothing in the widget is survey-specific
Used in core1 occurrence, the question time limit input in survey
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupNo. It needs an options key and a context key that Studio cannot write
Alternativesboolean_update_flag, integer, float

What the integer update-flag field does

Some numbers on a record are inherited from a global setting until somebody decides otherwise. A default time limit, a default lead time, a default threshold. The moment a user types their own number, that record should stop following the global default, and it should start following it again if they type the default back.

Odoo cannot detect that with a compute, because a compute cannot see who wrote the value. integer_update_flag can, because it lives inside the input. It renders as an ordinary integer field, and when the input fires its change event it compares what is now displayed against a reference value taken from the field's context, then writes the result of that comparison into a second boolean field.

Its sibling boolean_update_flag does the same for checkboxes. The two are written differently: the checkbox version overrides the component's onChange method, while this one attaches a listener to the raw input element, because an integer field's value is committed by a shared input hook rather than by a method the widget owns.

What this means for your team

The value of this pattern is that a settings change stops being frightening. An administrator can raise the default time limit and know that only the questions nobody customized will move. Without the flag the choice is between overwriting everyone's work and never being able to change the default again, and teams usually pick the second, which is how stale configuration accumulates.

Two limitations belong in the project plan rather than in a support ticket later. The comparison happens in the browser, so nothing that arrives through an import, the API or an automation rule updates the flag. And the flag is a plain boolean on the record, so it can be corrected server side when a bulk operation gets it wrong.

If your override values can run into the thousands, read the deep dive before you deploy. The comparison has a formatting bug that makes large numbers unreliable, and the workaround is a one-line option.

Supported options in Odoo 19

The widget declares no supported options of its own. Its two knobs are read in extractProps and never announced, so no tooling suggests them. Everything else in the table is inherited, because its extractor spreads the standard integer extractor before adding its own props. Read from integer_update_flag_fields.js and integer_field.js, Odoo 19.0.

OptionTypeWhat it does
flagFieldNamestring (options key, camelCase)Technical name of the boolean field that receives the comparison result. Spelled in camelCase in the source and required; snake_case is ignored.(since Odoo 18.0)
referenceValuenumber (context key)The number the typed value is compared against, supplied through the field's context attribute rather than options. Required and type-checked as a number.(since Odoo 18.0)
enable_formattingbooleanInherited from the integer widget. Set it to False to remove thousands separators, which also makes this widget's comparison exact above 999.(default: true)(since Odoo 17.0)
typestringInherited. Set to number to render a real HTML number input, which is also what makes min and max take effect.
stepnumberInherited. Step of the number input's spinner.
human_readablebooleanInherited. Displays large values compactly, for example 1k. Avoid it here: the compact string breaks the comparison even harder than a thousands separator.(default: false)(since Odoo 17.0)
decimalsnumberInherited. Only meaningful together with human_readable.(default: 0)(since Odoo 17.0)
minnumber<strong>Inherited and undeclared on the base integer widget too.</strong> Forwarded to the HTML input, so it only constrains input when type is number.(since Odoo 19.0)
maxnumber<strong>Inherited and undeclared on the base integer widget too.</strong> Same conditions as min.(since Odoo 19.0)

Watch the spelling and the location. flagFieldName is camelCase and belongs in options; referenceValue belongs in context. Both props are declared without the optional marker, so a missing or misspelled key produces a props validation error rather than a silent fallback. The inherited min and max are undeclared even on the base integer widget, and only take effect when the input is rendered as a real number input through type.

Working examples

The core usage, trimmed

<field name="is_time_customized" invisible="True"/>
<field name="time_limit" nolabel="1"
       widget="integer_update_flag"
       options="{'flagFieldName': 'is_time_customized'}"
       context="{'referenceValue': survey_session_speed_rating_time_limit}"/>

Both this field and the checkbox next to it write the same flag, so either one being customized marks the question.

Making large values compare correctly

<field name="threshold" widget="integer_update_flag"
       options="{'flagFieldName': 'threshold_overridden',
                  'enable_formatting': False}"
       context="{'referenceValue': default_threshold}"/>

Turning formatting off removes the thousands separator, which is what breaks the comparison above 999. Verified in the source, see the deep dive.

With inherited numeric bounds

<field name="threshold" widget="integer_update_flag"
       options="{'flagFieldName': 'threshold_overridden',
                  'type': 'number', 'min': 0, 'max': 600}"
       context="{'referenceValue': default_threshold}"/>

min and max come from the base integer widget and are passed to the HTML input, so they only constrain anything when type is number.

The thousands separator that breaks the comparison

The comparison line in the source is parseInt(this.formattedValue) !== this.props.referenceValue, and formattedValue is the getter the integer widget uses to fill the input. Unless formatting is disabled, that getter returns a localized string produced by formatInteger, which inserts thousands separators.

parseInt stops at the first character it cannot read. In an English locale parseInt("1,200") returns 1. So a user who types 1200 into a field whose reference value is 1200 gets 1 compared against 1200, the values differ, and the record is flagged as customized even though it matches the default exactly. The mirror case is just as bad: two different four-digit values can both reduce to the same leading digit and fail to flag.

Below 1000 nothing separates, which is why the core usage never trips over it. Survey time limits are seconds, and questions are rarely given a twenty-minute limit. Any reuse with larger numbers should pass enable_formatting: False, which makes formattedValue return the raw number and the comparison exact. Human-readable formatting is worse still, since it renders values as text like 1k.

The other structural detail is how the widget hooks the change. It cannot simply override a method, because an integer field's value is committed by the shared input hook rather than by the component. So it takes a reference to the input element and adds its own native change listener, cleaning it up when the element goes away. That is also why it reads the displayed string instead of the record value: at that point the string is what the widget has.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Same behavior on the development branch; only the hook and props syntax change.
Odoo 19.0VerifiedVerified against the shipped source. Byte-identical to Odoo 18; the base integer widget gained min and max and lost placeholder.
Odoo 18.0VerifiedFirst version. Same option key, context key and comparison.
Odoo 17.0Not availableWidget does not exist.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. The Odoo 18 and Odoo 19 files are byte-identical, so views move across untouched. What did change around it is the base integer widget: Odoo 19 dropped support for the placeholder attribute and added the undeclared min and max options, both of which this widget inherits. A view that relied on a placeholder here will lose it on Odoo 19 with no error.

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 read the following as direction rather than commitment; we re-verify this page after release.

Same behavior, tidier plumbing. The manual reference plus effect is replaced by a listener hook, and the props move to the new Owl schema syntax. The option key, the context key and the comparison line are unchanged, which means the thousands-separator behavior described above is still present on the development branch.

The core usage in the survey question form also survives unchanged.

Common problems and fixes

SymptomCause and fix
A value equal to the default is still flagged as customizedThe value is 1000 or more, so the formatted string carries a thousands separator and parseInt truncates it. Add 'enable_formatting': False to the options, which removes the separator.
Props error mentioning flagFieldNameThe key is missing or written in snake_case; only options.flagFieldName is read. Write options="{'flagFieldName': 'your_flag_field'}" exactly.
Props error mentioning referenceValueNo referenceValue in the field's context, or the expression yields a non-number. Add context="{'referenceValue': some_integer_field}" and confirm it evaluates to a number.
The flag never changesThe flag field is not loaded in the view, or the change came from an onchange rather than typing. Add the flag field to the view invisibly, and remember the widget only reacts to the input's own change event.
min and max do nothingThe input is rendered as text, which is the default, so the HTML constraints are inert. Add 'type': 'number' to the options, or validate server side.
The placeholder disappeared after upgrading to Odoo 19The base integer widget stopped extracting the placeholder attribute in Odoo 19. Use a label or help text instead; the placeholder cannot be restored through XML.
human_readable makes flagging erraticThe comparison parses the compact display string, so 1k is read as 1. Do not combine human_readable with this widget.

Integer update-flag field vs the alternatives

WidgetBest forKey difference
integer_update_flagKnowing that a person, not a compute, changed a numberListens to the input's change event and writes a second boolean field with the comparison result
boolean_update_flagThe same override tracking on a checkboxOverrides the component's onChange rather than hooking the input element
integerAn ordinary whole numberWrites one field and knows nothing about defaults or overrides
floatDecimal quantitiesDifferent type entirely; this widget only supports integer fields

Use this only when the distinction between a human edit and a recalculation is genuinely load-bearing. When it is not, an onchange or a computed field is simpler and also covers imports and API writes. For the same requirement on a checkbox, use boolean_update_flag, which core pairs with this widget in the very same block.

Frequently asked questions

Why does integer_update_flag mis-flag values above 999?+
It compares parseInt(this.formattedValue) against the reference value, and the formatted value carries a thousands separator. parseInt stops at the separator, so 1,200 is read as 1. Passing 'enable_formatting': False removes the separator and makes the comparison exact.
Where do its two settings go?+
flagFieldName goes in the field's options dictionary in camelCase, and referenceValue goes in the field's context attribute. Neither is declared in the widget's supported options, so no tooling will suggest either.
How is it different from boolean_update_flag?+
Same purpose, different mechanics. The checkbox version overrides the component's onChange method; this one attaches a native change listener to the input element, because an integer field's value is committed by a shared input hook.
Do imports update the flag?+
No. The comparison runs only in the browser when the input fires a change event. CSV imports, API writes and automation rules leave the flag untouched.
Can I use the standard integer options with it?+
Yes. Its extractor spreads the integer extractor first, so enable_formatting, type, step, human_readable, decimals, min and max all work. Two of them, min and max, are undeclared even on the base widget.

Numbers in your Odoo that nobody dares change?

Default values, per-record overrides and the reporting that has to survive both are a design problem before they are a coding problem. We work through that logic with your team and build it end to end on Odoo 16 through 19, browser side and server side.

Book a free consultation

How this page was produced

The two knobs, the listener approach, the inherited option set and the parseInt on the formatted value were read from integer_update_flag_fields.js and integer_field.js on the Odoo 19.0 branch, with the core usage taken from survey/views/survey_question_views.xml. The formatting behavior was traced through the integer widget's formattedValue getter and formatInteger. Version coverage comes from the same files on 16.0, 17.0, 18.0 and the development branch. Spotted an error? Tell us and we will correct the page.