Skip to main content
iVentureTeam

applicant_line_many2many

Applicant tags with the job position in front of the name. On a refusal wizard covering several vacancies, that prefix is the difference between knowing who you are rejecting and guessing.

Siddharth JambukiyaSiddharth JambukiyaOdoo Techno-Functional Consultant
August 27, 2026Updated September 7, 20264 min read
Technical nameapplicant_line_many2many
Field typesmany2many
Viewsform
Modulehr_recruitment, the Recruitment app
Used in core1 occurrence, the refuse reason wizard in hr_recruitment
VersionsOdoo 20.0, Odoo 19.0
No-code setupNo. It injects a recruitment-specific related field
Alternativesmany2many_tags, many2many_tags_avatar, applicant_char, many2many

What the applicant tags does

Refusing applicants is often a batch action: select several, choose a reason, send. The wizard confirms who is being refused by listing them as tags, and a list of names alone is ambiguous the moment two people share one, or the moment the selection spans two vacancies.

This widget removes that ambiguity by putting the job position in front of each name. The tag reads as the vacancy and the person, which is how a recruiter thinks about a candidate anyway.

The job is not something the view has to provide. The widget declares it as a related field on the tag records, so it is loaded automatically wherever the widget is used.

What this means for your team

Batch refusals are the highest-risk routine action in recruitment, because the consequence of including the wrong person is a rejection email that cannot be recalled. Anything that makes the confirmation list unambiguous is worth having, and the job prefix does it without a wider form.

The pattern is worth remembering for any batch wizard: the confirmation is the last point at which a mistake is cheap, so it should show whatever distinguishes the records rather than only their names.

Supported options in Odoo 19

The widget declares no options of its own. It spreads the tags widget's descriptor and adds one injected related field, so the options below are inherited. Read from applicant_line_many2many.js and the tags field, Odoo 19.0.

OptionTypeWhat it does
job_idinjected related fieldAdded by the descriptor to the fields loaded for each tag, so the job position is available for the label without the view requesting it.(since Odoo 19.0)
no_createbooleanInherited from the tags widget. Removes creation from the dropdown.(default: false)
no_quick_createbooleanInherited. Removes creation from the typed text while keeping the popup form path.(default: false)
color_fieldfieldInherited from the tags widget. Names an integer field used to color the tags.

The job field is injected, not requested. The descriptor adds it to the related fields loaded for each tag, so the view needs no extra declaration. The label is composed from that field and the applicant's display name, falling back to the name alone when there is no job.

Working examples

The core usage

<field name="applicant_ids"
       widget="applicant_line_many2many"/>

No options and no extra fields. The job position arrives with the tag data.

How a tag reads

Senior Developer - Jane Smith
Jane Smith            # no job position set

The separator and the order are fixed in the widget.

The plain tags widget

<field name="applicant_ids" widget="many2many_tags"/>

Names only, which is ambiguous the moment two applicants share one.

Injecting the field the label needs

The widget is thirty lines and does exactly two things.

It overrides the method that builds each tag's properties, composing the label from the job position and the applicant's display name, and using the name alone when the job is missing. That fallback matters: an applicant created without a vacancy would otherwise produce a tag beginning with an empty separator.

And its descriptor extends the related fields loaded for the tags with the job relation, so the data the label needs is present without the view asking for it. That is the cleaner of the two ways to get extra data onto a tag, the other being to read a field from the parent record, which several other widgets in Odoo do.

Everything else is inherited. The dropdown, the removal behavior and the tags widget's own options all work as usual, which is what makes this a genuinely small widget rather than a rewrite.

One implementation note for anyone extending it: the label is composed at tag-build time, so it follows changes to the underlying data without any additional wiring.

Version compatibility

VersionStatusNotes
Odoo 20.0In developmentNot released. Byte-identical to Odoo 19 on the development branch.
Odoo 19.0VerifiedFirst version. Verified against the shipped source.
Odoo 18.0Not availableWidget does not exist. The wizard listed applicants without the job prefix.
Odoo 17.0Not availableWidget does not exist.
Odoo 16.0Not availableWidget does not exist.

Upgrade note. The widget is new in Odoo 19. On Odoo 18 and earlier the refusal wizard listed applicants without the job prefix, so an upgrade improves the wizard with the standard views and nothing needs migrating.

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 and this may still change; we re-verify the page after release.

Byte-identical. The file on the development branch matches Odoo 19 exactly, including the injected related field and the label composition.

Common problems and fixes

SymptomCause and fix
Tags show names onlyThose applicants have no job position, which is the documented fallback. Expected. Set the vacancy on the applicant if the prefix is wanted.
The prefix is missing everywhereThe field is using the plain tags widget rather than this one. Set widget="applicant_line_many2many" on the field.
The related job field is not loadedA customization replaced the descriptor's related fields. Keep the injected field when overriding the descriptor.
The separator is wrong for my languageThe label format is fixed in the widget. Copy the widget with your own composition if the format matters.
Options are ignoredThe widget declares none; inherited tag options work normally. Use the tags widget's options as usual.
Missing widget errorThe recruitment module is not installed in that database. Install Recruitment, or use the plain tags widget.

Applicant tags vs the alternatives

WidgetBest forKey difference
applicant_line_many2manyConfirmation lists of applicants that may span several vacanciesComposes each tag label from an injected job field plus the applicant's name
many2many_tagsAny relation shown as tagsNames only, with no injected context
many2many_tags_avatarPeople shown with a pictureAdds a face rather than a job title
applicant_charA clickable applicant name on an attachmentA text cell with navigation, not a relation
many2manyA relation shown as a tableColumns rather than tags, so the job can be its own column

Use the plain tags widget wherever names alone are unambiguous. Where they are not, injecting a related field and composing the label is the tidy approach, and it is worth copying for any batch wizard whose confirmation list needs more than a name. Avatar variants solve a different half of the same problem by adding a face rather than a context.

Frequently asked questions

Why does each tag start with a job title?+
So a batch of applicants spanning several vacancies is unambiguous. The label is composed from the applicant's job position and their display name.
What if an applicant has no job position?+
The tag falls back to the name alone, which avoids a label beginning with an empty separator.
Does the view need to load the job field?+
No. The widget's descriptor injects it into the related fields loaded for each tag, so it arrives automatically.
Does it support the tags widget's options?+
Yes, all of them. It spreads that descriptor and only adds the injected field and the label composition.
Which versions have it?+
Odoo 19 onwards, and byte-identical on the Odoo 20 development branch.

Recruitment decisions with the right candidate in front of you

Pipelines that span several vacancies need screens that keep the context visible, especially at the point of rejection. We implement and tune Odoo Recruitment on versions 16 through 19.

Book a free consultation

How this page was produced

The label composition, its fallback and the injected related field were read from applicant_line_many2many.js on the Odoo 19.0 branch, with the inherited option set read from the tags field in web. The usage comes from hr_recruitment/wizard/applicant_refuse_reason_views.xml. Version coverage comes from the absence of the file on 16.0, 17.0 and 18.0, and a byte comparison against the public development branch. Spotted an error? Tell us and we will correct the page.