Skip to main content
iVentureTeam

char_with_placeholder_field

A char field that never looks empty: char_with_placeholder_field shows the placeholder as a muted value, so users see the default Odoo will apply before it is applied.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 18, 2026Updated August 18, 20265 min read
Technical namechar_with_placeholder_field
Field typeschar, text
Viewsform, list (accounting wizards and expense views)
Moduleaccount, installed with Invoicing or Accounting
Used in core7 occurrences across account (payment register wizard), l10n_account_withholding_tax, hr_expense
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0
No-code setupNo. Set in view XML; the closest Studio concept is the general Placeholder property, which does not render into the value
Alternativeschar, text, CopyClipboardChar

What the Char with Placeholder field does

A standard char field with a placeholder shows the hint only while the input is focused and editable; the moment the field renders readonly or sits in a list cell, an empty value is just blank. char_with_placeholder_field closes that gap. It extends the char widget and overrides exactly one getter: formattedValue returns the stored value if there is one, otherwise the placeholder.

The template adds a text-muted class whenever the record has no stored value, so the fallback reads as gray suggestion text rather than data. Everything else, options, types, editing behavior, is the plain char widget: the descriptor is a spread of charField with only the component swapped.

What this means for your team

The widget exists because of a small but expensive UX problem in accounting flows: fields whose value Odoo computes at confirmation time. Take the payment reference in the register payment wizard. Leave it empty and Odoo will generate one; but a blank box invites users to either invent their own reference or hesitate over whether something is missing. Rendering the to-be-computed value as a muted placeholder answers the question before it is asked: this is what you will get if you do nothing, type only if you want something else.

That pattern, "show the default, allow the override", is worth stealing for your own forms: reference numbers, generated labels, computed descriptions. It reduces both data noise from users who felt obliged to type something and support questions from users who feared the blank meant an error. The withholding tax and expense teams at Odoo adopted the same widget for exactly those reasons.

Supported options in Odoo 19

Verified against char_with_placeholder_field.js in the Odoo 19.0 account module. The widget declares nothing of its own; the descriptor spreads charField, so the char widget's declared option and its extractProps-only knobs apply unchanged.

OptionTypeWhat it does
placeholder_fieldfield nameInherited from the char widget: a char or text field on the record whose value serves as the dynamic placeholder, which this widget then also renders as the empty-value fallback.
dynamic_placeholderbooleanInherited extractProps-only knob of the char widget enabling the dynamic placeholder popup used by mail templates. Not declared in any options panel.
dynamic_placeholder_model_reference_fieldfield nameCompanion extractProps-only knob naming the field that holds the model for dynamic placeholder resolution.

The placeholder itself is not an option. It comes from the standard placeholder attribute on the field element, or dynamically via the inherited placeholder_field option. If neither is set, the widget behaves exactly like a plain char field: empty renders empty.

Working examples

Static placeholder as fallback display

<field name="communication"
       widget="char_with_placeholder_field"
       placeholder="Auto-generated on confirmation"/>

Empty cells now read the hint in muted text, in readonly renders too.

Dynamic placeholder from another field

<field name="reference"
       widget="char_with_placeholder_field"
       options="{'placeholder_field': 'suggested_reference'}"/>

The record computes suggested_reference, and the widget displays it as the muted fallback until the user types a real value. This is the core pattern: pair the widget with a computed char field holding the default.

Value, placeholder, and what actually saves

The subtle part is which layer produces what you see.

While editing, the browser's native placeholder behavior applies, exactly as on a plain char input: gray hint inside the input, gone the moment a character is typed.

When rendered as text, in readonly forms or list cells, the char widget prints formattedValue, and that is the getter this widget overrides. Stored value wins; placeholder is the fallback; the template's conditional text-muted class distinguishes the two visually.

What is saved is unaffected. The placeholder never becomes data; if the user saves without typing, the field stays empty in the database and whatever server logic computes the real value runs as designed. A version note for patchers: 18.0 read the component's placeholder getter, 19.0 reads this.props.placeholder directly. Same rendering, different code path.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. File byte-identical on the development branch. See below.
Odoo 19.0VerifiedVerified against the shipped source; fallback reads props.placeholder directly.
Odoo 18.0VerifiedFirst version with this widget; same behavior via the component's placeholder getter.
Odoo 17.0Not availableWidget does not exist; the file is absent from the 17.0 tree.
Odoo 16.0Not availableWidget does not exist; the file is absent from the 16.0 tree.

Upgrade note. The widget appeared in 18.0. Views coming from 17.0 or earlier that want this behavior must switch the widget name explicitly; there is nothing to migrate automatically. From 18 to 19 the only change is internal (the fallback reads the prop instead of the component getter).

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. As always, the development branch is unstable until release and we re-verify this page against the shipped version.

For this widget the current development branch shows no change at all: the file is byte-identical to 19.0. Whatever else Odoo 20 reworks in the char widget family will be inherited through the descriptor spread, which is another reason the odoo20 story here is simply "watch the base char widget".

Common problems and fixes

SymptomCause and fix
The field looks filled but exports show it emptyThe muted text is the placeholder fallback, not stored data. Working as designed; the muted styling is the cue. Type a value to store one.
Empty cells still render blankNo placeholder attribute and no placeholder_field option are set, so there is nothing to fall back to. Add placeholder="..." on the field element or a placeholder_field option.
The fallback text is not mutedCustom CSS overrides text-muted, or the record actually has a stored value equal to the hint. Inspect the cell: the widget only adds text-muted when the stored value is empty.
widget="char_with_placeholder_field" errors on Odoo 17The widget shipped in 18.0. Use a plain char field on 17, or backport the component in a custom module.
Dynamic placeholder does not updateThe field named in placeholder_field is not loaded in the view or is not recomputed. Ensure the source field is in the view (invisible is fine) and its compute triggers on the right dependencies.

Char with Placeholder field vs the alternatives

WidgetBest forKey difference
char_with_placeholder_fieldChar fields whose empty state should show the computed defaultRenders the placeholder as a muted value instead of a blank cell
charOrdinary text without fallback displayPlaceholder shows only in the editable input, never as rendered text
textMultiline notesMultiline editing, standard placeholder behavior
CopyClipboardCharValues users copy out of OdooAdds a copy button rather than a fallback display

The practical test: does an empty cell need to communicate the default? If yes, this widget. If the field just needs a typing hint, the plain char placeholder already does that while editing.

Frequently asked questions

What does char_with_placeholder_field do in Odoo?+
It renders a char field that falls back to its placeholder when empty: the placeholder text appears as a muted value in readonly renders and list cells, instead of a blank. Odoo's accounting uses it for fields like the payment reference, where an empty field means "Odoo will generate this", and the placeholder shows what will be generated.
Is the placeholder saved to the database?+
Never. The fallback is purely display. If the user saves without typing, the field remains empty and any server-side default logic runs normally. The muted styling exists precisely to signal that the text is not stored data.
Can the placeholder come from a computed field?+
Yes, through the inherited placeholder_field option: point it at a char field on the same record, typically a computed one holding the suggested value. That is the strongest use of this widget, a live preview of the default.
Which Odoo versions have char_with_placeholder_field?+
18.0 and 19.0, in the account module, so any database with Invoicing installed has it. It does not exist in 17.0 or earlier, and the Odoo 20 development branch currently carries it unchanged.
Does it work on multiline text fields?+
The inherited descriptor supports char and text types. The component renders like the char widget, single line, so for genuinely multiline content the plain text widget is usually the better fit despite losing the fallback display.
How is this different from a normal placeholder?+
A normal placeholder is visible only inside an editable, empty input. This widget also shows it wherever the value renders as text: readonly forms and list columns. One getter override in the source is the entire difference.

Forms that make users guess the default?

Small display decisions like a visible computed reference save real support load. We refine Odoo accounting screens, from wizard UX to localization quirks, so your finance team stops second-guessing what Odoo will fill in.

Book a free consultation

How this page was produced

This page was verified by reading char_with_placeholder_field.js and its template in the Odoo 19.0 account module, plus the char_field.js descriptor it spreads, and by checking the widget's seven core usages. Version availability was confirmed by listing the file across the 16.0 through master branches: absent before 18.0, byte-identical on master. Spotted an error? Tell us and we will correct the page.