Skip to main content
iVentureTeam

code

One widget, two names: code and ace are the same registered descriptor that swaps a plain textarea for a real Ace editor with syntax highlighting, dark mode, and careful save semantics.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 24, 2026Updated August 24, 20265 min read
Technical namecode
Field typestext, html
Viewsform
Also registered asace (same descriptor); sibling code_ir_ui_view for ir.ui.view arch editing (19.0)
Moduleweb, present in every Odoo database
Used in core3 occurrences across 2 modules: website, marketing_card
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupNo. Studio's widget picker does not offer it; apply it in view XML
Alternativestext, html, domain

What the Ace Editor field does

Some fields hold code: QWeb templates, XML snippets, custom website head tags, computed expressions. Edited in a plain textarea they are unreadable and easy to break. The code widget replaces the textarea with an embedded Ace editor: line numbers, bracket matching, syntax coloring for the language you declare, and a dark theme that follows the user's color scheme.

The widget is deliberately thin. It declares one option, mode, which selects the Ace language mode; everything else is the shared CodeEditor component from the web core. Two details from the source are worth knowing up front: the default mode is qweb, and a mode of xml is silently remapped to qweb as well, because Odoo's QWeb mode is its XML mode with QWeb directives on top.

And if you have seen widget="ace" in older views: same widget. Both names point at one descriptor in the registry.

What this means for your team

The practical value is guardrails for the semi-technical. Website managers pasting analytics tags into the custom head code, marketers adjusting a card template, consultants editing an automation expression: with syntax coloring, a typo that would silently break rendering is visible before saving.

The save behavior is also friendlier than it looks. The widget compares the editor content against the initial value and only marks the record dirty on a real change, and it commits the editor content when the form saves rather than on each keystroke, so autosave-style side effects do not fire while someone is mid-edit. For teams doing serious view or template development, the in-form editor is still a convenience, not an IDE; version control and proper deployment discipline remain the answer for anything that matters.

Supported options in Odoo 19

Verified against ace_field.js in the Odoo 19.0 web module: one declared option, read by extractProps and passed to the CodeEditor.

OptionTypeWhat it does
modestringAce language mode for highlighting: python, xml, qweb, javascript, scss and friends. The component remaps xml to qweb internally. Unknown modes degrade to plain text.(default: qweb)(since Odoo 17.0)

The mode list is Ace's, filtered by what Odoo ships. Practically useful values are python, xml (which becomes qweb), qweb, javascript, scss and css. An unknown mode does not error; the editor simply falls back to plain text coloring.

Working examples

How core applies it (website custom code)

<field name="custom_code_head" widget="code" options="{'mode': 'xml'}"/>

A Python expression field

<field name="compute_expression" widget="code" options="{'mode': 'python'}"/>

Default mode (QWeb)

<field name="arch_snippet" widget="code"/>

Omitting the option gives you QWeb highlighting, which is the right default for template-ish XML.

Save-time commits and the widget's history

The commit path is the part most customizations get wrong when they replace this widget. The component keeps the edited value locally and listens on the record model's bus for two events: the urgent-save signal (browser closing, navigation) and the local-changes collection that runs before any save. Only then does it push the value into the record, and only if the content differs from the value it started from. It also emits the standard dirty-flag event so the form's unsaved-changes indicator behaves. The consequence: server-side onchange logic on a code field fires at save time, not while typing, which is almost always what you want on large text.

Reading vs editing is driven by the standard readonly prop, and the initial value tracks record changes through a record observer, so switching records in a form keeps the editor honest.

Version notes from the source: 16.0 loaded the Ace library and its three mode files directly in the widget and registered only the ace name for text fields; 17.0 introduced the shared CodeEditor component, the code alias, the mode option and html-field support. Since 19.0 there is also code_ir_ui_view, a sibling registration wrapping the same descriptor with a view-editor variant used for ir.ui.view architecture.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Development branch adds a lineWrapping boolean option and migrates to the new props system. Re-verified after launch.
Odoo 19.0VerifiedVerified against the shipped source. Adds the code_ir_ui_view sibling registration.
Odoo 18.0VerifiedSame option, same dual registration, same types as 19.0.
Odoo 17.0VerifiedIntroduces the code alias, the mode option, the shared CodeEditor and html support.
Odoo 16.0Partial / changedRegistered only as ace, text fields only; loaded the Ace library and python, xml and qweb modes directly.

Upgrade note. Views using widget="ace" keep working on every version, but standardize on code going forward; it is the name core uses in new views. Views written for 16.0 that relied on text-only support gain html support from 17.0 with no change needed.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. The notes below come from the public development branch, which can change until feature freeze; we re-verify after release.

The development branch adds a second option, lineWrapping, a boolean defaulting to false that soft-wraps long lines in the editor. Two details for the curious: the option name is camelCase, unusual for view options, and its declared label in the source currently reads "lineWrapping Lines", which looks like a copy-paste slip that may be cleaned up before release. The component also migrates to the new frontend props system as part of the framework-wide change. The mode option, both registrations and the save behavior are unchanged.

Common problems and fixes

SymptomCause and fix
widget="code" does nothing on Odoo 16The code alias arrived in 17.0; 16.0 only registered ace. Use widget="ace" on 16.0 views.
XML highlighting looks like QWebThe component remaps mode xml to qweb by design; QWeb mode is Odoo's XML mode. Nothing to fix; directives simply get extra coloring.
onchange on the field does not fire while typingThe widget commits on save signals, not per keystroke, after comparing against the initial value. Expected; trigger logic on save, or use a plain text widget if per-keystroke reaction is essential.
Editor renders with a dark theme unexpectedlyThe theme follows the color_scheme cookie: dark scheme loads monokai automatically. Switch the user's color scheme; there is no per-field theme option.
No highlighting for an exotic languageOnly the modes Odoo ships with its Ace build are available; unknown modes fall back to plain text. Stick to python, qweb, javascript, scss or css, or add the mode file in a custom module.

Ace Editor field vs the alternatives

WidgetBest forKey difference
codeText fields holding code, templates or markupFull Ace editor with language modes and save-time commit semantics
textPlain multi-line notesSimple textarea, no highlighting, immediate standard field behavior
htmlRich content authored visuallyWYSIWYG editor writing HTML, not a code surface
domainDomain expressions specificallyStructured domain builder with count preview instead of raw text

The rule of thumb: code for machine-readable text a human edits, html for rich content a human writes, text when neither highlighting nor rich editing helps.

Frequently asked questions

What is the difference between widget="code" and widget="ace" in Odoo?+
None. Both names are registered against the same descriptor in ace_field.js. The ace name is the original (and the only one on 16.0); code was added in 17.0 and is what core views use now.
Which languages can the code widget highlight?+
Whatever Ace modes Odoo ships: python, qweb (which also serves xml, since the widget remaps xml to qweb), javascript, scss, css and a few others. The default when no mode is set is qweb. Unknown modes degrade gracefully to plain text.
Does the code widget save on every keystroke?+
No. It tracks whether the content differs from the initial value and commits only when the form saves (or the browser is about to leave), which keeps onchange side effects from firing mid-edit on large text.
Can I use the code widget in Odoo Studio?+
Studio's widget picker does not offer it. Add it through view XML with widget="code" and, optionally, options="{'mode': 'python'}". The field must be of type text or html (text only on 16.0).
What is code_ir_ui_view?+
A 19.0 sibling registration that wraps the same descriptor with a view-architecture-aware editor component, used when editing ir.ui.view arch in the backend. For ordinary code fields, keep using code.
What changes for the code widget in Odoo 20?+
The development branch adds a lineWrapping boolean option (camelCase, default false) for soft-wrapping long lines, alongside the framework-wide props migration. Unstable until the September 2026 release; we re-verify after launch.

Editing Odoo templates in a form field?

Custom website head code, QWeb report tweaks and expression fields are where quick edits quietly break production. We set up proper development workflows for Odoo teams, and build the custom views, widgets and editors that make in-house maintenance safe on Odoo 16 through 19.

Make my customizations safe

How this page was produced

This page was verified by reading ace_field.js on the Odoo 19.0 branch, diffing it against 16.0, 17.0, 18.0 and the public development branch, and checking the sibling ir_ui_view_ace registration and the core usages in website and marketing_card view XML. The xml-to-qweb remapping, the dual registration and the save-bus behavior are read from the source, not the documentation, which does not describe this widget. Corrections welcome via our contact page.