Skip to main content
iVentureTeam

additional_identifiers_button

The dropdown half of Odoo 20's additional identifiers pair. It offers only the types this partner has not used yet, in an order the server decides.

September 18, 2026Updated September 18, 20264 min read
Technical nameadditional_identifiers_button
Field typesjson
Viewsform
Also registered asPaired with additional_identifiers_list, which renders and edits the values
Moduleweb, present in every Odoo 20 database
Used in core3 uses across Odoo 20 Community and Enterprise views, excluding tests. Does not exist in Odoo 19.
VersionsOdoo 20.0
No-code setupNo. The source states it is only for the additional_identifiers field on the res.partner form.
Alternativesadditional_identifiers_list, json, char

What the additional_identifiers_button widget does

This is the Add control for a partner's additional identifiers. It sits next to additional_identifiers_list, and both widgets point at the same JSON field: this one adds a type, the other renders and edits the values.

The dropdown is built by subtracting what the record already has from what the metadata offers:

get identifiersInDropdown() {
    const typesInUse = Object.keys(this.state.identifiers);
    return Object.entries(this.state.metadata)
        .filter(([k, v]) => !typesInUse.includes(k) && !v.display_optional)
        .map(([k, v]) => ({
            identifierType: k,
            label: v.label || k,
            help: v.help || "",
            sequence: v.sequence || 100,
        }))
        .sort((a, b) => a.sequence - b.sequence);
}

Selecting an entry writes the type with an empty value, which makes it appear in the list widget ready to fill.

What this means for your team

The useful behavior here is the subtraction. A user only ever sees identifier types they have not already added, so the menu gets shorter as the contact gets more complete rather than presenting the same long list every time.

As with its sibling, nothing about which types exist is controlled from the view. If your team needs an identifier that is not on the menu, that is a server-side or localization question.

Working examples

The standard pairing. Both widgets take the same field name:

<field name="additional_identifiers" widget="additional_identifiers_list"/>
<field name="additional_identifiers" widget="additional_identifiers_button"/>

Using the button alone is legal but unhelpful: types can be added and then never filled in, because the editing interface lives in the list widget.

How the metadata field controls what users see

Both widgets read the same companion field, declared as a dependency on each descriptor:

const METADATA_FIELD = "available_additional_identifiers_metadata";

const metadataFieldDependency = [{ name: METADATA_FIELD, type: "json", readonly: true }];

That metadata drives everything visible: each identifier type's label, its help text, its sort order and whether it is offered at all. None of it lives in the view, so a module adding a new identifier type changes what users see without touching any XML.

The display_optional flag is the part worth understanding, because it has three states rather than two:

  1. Unset. The type is offered in the Add dropdown and appears in the list once chosen. This is the normal case.
  2. "show". The type is always rendered in the list, empty and ready to fill, and is never offered in the dropdown because it is already there.
  3. "hide". The type is not offered in the dropdown at all. It only appears if the record already has a value for it.

The dropdown filter reads !v.display_optional, so any value of that flag removes the type from the Add menu. That is the single rule behind both the show and hide behaviors.

One more detail that surprises people: clearing a value does not store an empty string, it removes the key entirely. onUpdateValue trims the input and calls delete this.state.identifiers[identifierType] when the result is empty. So a type the user blanks out disappears from the list unless its metadata marks it "show". Writes are debounced by 50 milliseconds, so rapid typing produces one record update rather than one per keystroke.

Finally, the JSON parsing is deliberately forgiving. parseJson catches any error and returns an empty object, which means malformed stored data renders as an empty widget rather than a broken form. Quiet, but worth knowing when a partner shows no identifiers and you expect some: check the stored value before the view.

Version compatibility

VersionStatusNotes
Odoo 19.0Not availableDoes not exist, and neither does the field it acts on.
Odoo 20.0VerifiedIntroduced in Odoo 20. Verified against the shipped 20.0 source.

This widget does not exist before Odoo 20.

What is changing in Odoo 20

Introduced in Odoo 20 alongside additional_identifiers_list. Odoo 19 has neither, and no additional_identifiers field for them to act on.

Both are written against the Odoo 20 runtime, using useProps and OWL 3's proxy for state, so neither can be backported without a rewrite.

Common problems and fixes

SymptomCause and fix
A type is missing from the Add dropdownEither the record already uses it, or its metadata sets display_optional, which excludes it from the menu. Check the stored identifiers and the metadata. A 'show' type is already rendered in the list instead.
The dropdown is emptyEvery offered type is already in use, or the metadata field is empty or malformed. Inspect the metadata the server produces; malformed JSON is parsed to an empty object.
A type was added but cannot be filled inThe button only adds the key with an empty value. Editing happens in additional_identifiers_list. Place both widgets on the form, pointing at the same field.
Types appear in an unexpected orderOrdering comes from the metadata sequence, defaulting to 100 when unset. Set sequence values server-side. The view cannot reorder them.

Additional_identifiers_button widget vs the alternatives

WidgetBest forKey difference
additional_identifiers_buttonAdding an identifier type a partner does not yet haveOffers only unused types, ordered by server metadata
additional_identifiers_listViewing and editing the valuesThe editing half of the same pair
jsonSeeing the raw stored structureRead-only text, no adding
charA single identifier on your own modelA real column, so it is searchable and reportable

Nothing else understands the metadata shape, so there is no alternative widget. Pair it with the list widget rather than using it alone, since a type added here can only be given a value there.

Frequently asked questions

Why is an identifier type missing from the Add dropdown in Odoo 20?+
Either the record already uses it, since the dropdown subtracts types in use, or its metadata sets display_optional, which removes it from the menu. A type flagged 'show' is already rendered in the list widget instead.
Do I need both additional identifiers widgets?+
In practice yes. The button only adds a type with an empty value; the value is filled in additional_identifiers_list. Place both on the form pointing at the same field.
How is the dropdown ordered?+
By a sequence value in the server-computed metadata, defaulting to 100 for types that do not set one. The view has no control over the order.

Contact records that never quite match the tax rules?

Identifier types, tax mappings and fiscal positions have to agree before an invoice is correct in a new market. We set up Odoo localizations so the contact form, the tax engine and the reports tell the same story.

Talk to an Odoo consultant

How this page was produced

Verified by reading addons/web/static/src/views/fields/additional_identifiers/additional_identifiers.js on the 20.0 branch of a local clone of the official Odoo repository, with the dropdown getter quoted in full above. The metadata dependency, the display_optional filtering and the sequence default of 100 are read directly from that file, and the scope limitation from its own comment. The usage count comes from scanning every non-test XML file in Community, Enterprise and odoo/addons. Corrections welcome via our contact page.