Skip to main content
iVentureTeam

CopyClipboardButton

Of Odoo's three clipboard widgets, CopyClipboardButton is the only one that hides the value: just a button that puts the field's content on the clipboard, and nothing at all when the field is empty.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 21, 2026Updated August 21, 20266 min read
Odoo 19 form view showing the CopyClipboardButton widget as a primary Copy URL button in a button box, with no field value displayed next to it.
Technical nameCopyClipboardButton
Field typeschar, text
Viewsform, list
Moduleweb, present in every Odoo database
Used in core3 occurrences across 2 modules: website_sale product feed views and website_event
VersionsOdoo 20.0, Odoo 19.0, Odoo 18.0, Odoo 17.0, Odoo 16.0
No-code setupNo. Applied via the widget attribute in view XML
AlternativesCopyClipboardChar, CopyClipboardURL, url

What the Copy button does

Odoo ships one source file with three clipboard widgets. CopyClipboardChar and CopyClipboardURL display the field's value with a copy control attached. This page's widget is the third and the odd one out: CopyClipboardButton shows a standalone button and never displays the value. Click it, and the field's raw content is on the clipboard; a brief "Copied" confirmation replaces the label.

That makes it the right choice for values that are long, ugly, or pointless to read: feed URLs, API keys, webhook endpoints, tokens. Core's canonical use is the product feed URL in website_sale, a generated address nobody benefits from seeing, placed in the form's button box as a simple "Copy URL" action.

The whole rendering is one template line with a guard: if the field has no value, the widget renders nothing. There is no empty state to style and no dead button to explain; the control simply appears once the value exists.

What this means for your team

The difference between "select the URL, Ctrl+C, hope you got all of it" and one labeled button sounds trivial until you watch non-technical users handle machine-generated strings. Partial copies of feed URLs and keys are a real support category, and this widget removes the failure mode by never letting the user near the raw text.

It also has a mild security-adjacent benefit: values that should not be casually shoulder-surfed, tokens, private links, can be made copyable without being displayed. That is presentation-level discretion, not protection, since the value still travels to the browser and sits in the DOM props, but it keeps screens and screenshots clean.

Design-wise, treat it as an action, not a field. Core places it in the button box with a verb label via string. A copy button lost in the middle of a field grid with the default "Copy" label tells the user nothing about what they are copying; "Copy feed URL" in the header does.

Supported options in Odoo 19

Verified against copy_clipboard_field.js in the Odoo 19.0 web module. One real option, plus two view attributes that do the configuring work and are easy to miss because they are not options at all.

OptionTypeWhat it does
btn_classstringBootstrap button flavor slotted into btn-{value}. New in Odoo 19; 18 hardcoded btn-primary. Any Bootstrap suffix works, including outline and link styles.(default: primary)(since Odoo 19.0)

The label and the disable rule are attributes, not options. string="Copy URL" sets the button text and disabled="state != 'done'" takes a Python expression evaluated against the record, including virtual ids. Only btn_class goes inside options="{...}". The disabled attribute is parsed for all three clipboard widgets but only this Button variant's template consumes it, a quirk confirmed in the source.

Working examples

As core uses it, in the button box

<div name="button_box">
    <field name="url" string="Copy URL" widget="CopyClipboardButton"/>
</div>

Secondary styling with the 19-new option

<field name="api_key" string="Copy key"
       widget="CopyClipboardButton"
       options="{'btn_class': 'secondary'}"/>

The value slots into btn-{value}, so any Bootstrap button flavor works: secondary, outline-primary, link.

Conditionally disabled

<field name="share_url" string="Copy link"
       widget="CopyClipboardButton"
       disabled="not is_published"/>

The expression is evaluated per record, so the button greys out until the record is published.

What the source guarantees, and what it does not

Reading the file end to end turns up details that matter in practice.

Empty means invisible. The Button template is guarded by t-if="props.record.data[props.name]". The sibling widgets keep their field visible when empty; this one vanishes entirely. If your layout needs a stable placeholder, reserve the space or show a muted note conditionally.

It copies exactly what is stored. The template hands record.data[name] to the copy component. There is no formatting pass, no URL prefixing (unlike the display behavior of the URL widget family), no trimming. Whatever the database holds is what lands on the clipboard.

Clipboard needs a secure context. The underlying CopyButton uses the async browser clipboard API, which browsers only expose on HTTPS or localhost. On a plain-HTTP staging box the button renders and does nothing, which reliably files a false bug.

The type in the CSS hook is the field type. The class is o_btn_{type}_copy where type is the field's technical type, so a char field yields o_btn_char_copy. Useful for targeted styling, confusing if you expected the widget name.

Unsupported types are not enforced. Unlike its siblings, the Button descriptor declares no supportedTypes, so nothing stops you putting it on, say, an integer field; it will copy the raw value. Treat char and text as the intended surface.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Button variant unchanged on the development branch; sibling widgets get icon and styling changes.
Odoo 19.0VerifiedVerified against the shipped source. btn_class option introduced.
Odoo 18.0Partial / changedSame behavior with btn-primary hardcoded; no btn_class option.
Odoo 17.0Partial / changedstring and disabled attributes present, but the button has no primary styling and no btn_class.
Odoo 16.0Partial / changedWidget exists in the legacy implementation; no string, disabled, or styling configuration.

Upgrade note. XML written for 16 keeps working through 19, but styling drifted: 17 rendered a bare rounded button, 18 hardcoded btn-primary, and 19 made the flavor configurable with btn_class. A pre-19 view that relied on the default look may need btn_class set after migrating to keep visual consistency. The string and disabled attributes exist since 17; 16 had neither.

What is changing in Odoo 20

Odoo 20 is expected at Odoo Experience in Brussels, 24 to 26 September 2026. These notes are read from the public development branch, which is unstable until feature freeze; we re-verify against the shipped release.

For the Button variant specifically, behavior is unchanged: same template guard, same btn_class option with the primary default, same registration. The visible master changes hit the siblings: the Char and URL variants' copy icons switch from Font Awesome clipboard and link glyphs to the new assignment icon set, and their attached-button styling moves from btn-sm to btn-link btn-link-inline. The file also picks up the framework-wide props-validation migration, which exports the shared props for reuse but changes nothing in XML.

Common problems and fixes

SymptomCause and fix
The button does not appear at allThe field is empty; the template renders nothing without a value. Ensure the field is set, or display a conditional placeholder while it is empty.
Clicking the button copies nothingThe clipboard API requires a secure context, so plain HTTP deployments fail silently. Serve Odoo over HTTPS; on localhost it works without certificates.
Widget not found, field renders as plain textThe registry name is case-sensitive CamelCase. Write widget="CopyClipboardButton" exactly.
btn_class has no effect after copying a view from Odoo 19 to 18The option is 19-new; 18 hardcodes btn-primary. Drop the option on 18 or restyle via CSS on the o_btn_char_copy class.
disabled option inside options dict is ignoreddisabled is a view attribute carrying a Python expression, not an option. Write disabled="expression" directly on the field element.
Copied value differs from what a link shows on screenThe button copies the raw stored value with no formatting or prefixing. Store the exact string users should receive, or use CopyClipboardURL to show what will be copied.

Copy button vs the alternatives

WidgetBest forKey difference
CopyClipboardButtonCopying long or sensitive values without displaying themButton only; the value never renders and empty fields show nothing
CopyClipboardCharShort codes users read and copyShows the value with an attached copy control
CopyClipboardURLLinks users may click or copyRenders the value as a link; copies the raw stored string
urlPlain clickable linksNo copy affordance at all

Pick by what the user needs to see: Button when the value is noise, Char or URL when the value doubles as information, and a plain char field when copying is incidental.

Frequently asked questions

How is CopyClipboardButton different from CopyClipboardChar and CopyClipboardURL?+
The siblings display the field's value with a copy control attached. The Button variant displays only a button and never shows the value; when the field is empty it renders nothing at all. All three live in the same source file in the web module.
How do I change the button's label?+
Set the string attribute on the field, for example string="Copy URL". The default label is Copy, and after a click it briefly shows Copied. This attribute exists since Odoo 17.
Can I disable the button conditionally?+
Yes, with the disabled attribute carrying a Python expression evaluated against the record, such as disabled="not is_published". Note it is an attribute, not an option, and among the three clipboard widgets only the Button template actually honors it.
Why does the copy do nothing on our test server?+
Browsers expose the clipboard API only in secure contexts. If the test server runs plain HTTP, the click fails silently. HTTPS, or localhost during development, fixes it.
What styles can btn_class take?+
Anything Bootstrap accepts after btn-, since the value is interpolated into the class: secondary, success, outline-primary, link. The default is primary. The option exists only from Odoo 19.
Does the widget hash or protect the value since it is hidden?+
No. Hiding is purely visual; the value is present in the page's component props and lands on the clipboard in plain text. For actual secrets, control access to the field itself with groups or field-level access rules.

Feeds, keys, and webhooks piling up in your Odoo?

Copy buttons usually appear where Odoo meets another system: product feeds, portals, integrations. We build those integrations properly, from generated URLs and API keys to the sync jobs behind them, on Odoo 16 through 19.

Book a free consultation

How this page was produced

This page was verified by reading copy_clipboard_field.js and copy_clipboard_field.xml on the Odoo 19.0 branch, and diffing the same file across 16.0, 17.0, 18.0, and master to date the attributes and the btn_class option. Core usage was confirmed in the website_sale product feed views. Button behavior, the empty-field guard, and the secure-context requirement were exercised on a clean Odoo 19 database, where the screenshot was captured. Corrections welcome via our contact page.