I am having a hard time getting a field (many2many_tags) to dynamically reload with selection options after the user has selected from another field. This is a very common trait of the web (select a country, you then dynamically load up the provinces/states of the country in the next select box for the user to pick). The issue I am having is that the second field never updates in the UI. I can see in the logs that the list to feed the field is indeed updated, but the UI itself never shortens or reloads the list.
Here is the XML of the first field:
<field name="arch" type="xml">
<form string="Report Wizard Base">
<!-- Body Fields -->
<group>
<field name="start_date"/>
<field name="end_date"/>
</group>
<group>
<field name="pos_config_ids" widget="many2many_tags"/>
</group>
<group string="Email Options">
<field name="delivery_format"/>
<field name="email_to" placeholder="email@email.com"/>
</group>
And then the inherited view adds in the Second select:
<!-- Insert employee filters before the Email Options group -->
<xpath expr="//field[@name='delivery_format']/.." position="before">
<group string="Employee Filters">
<field name="employee_ids" widget="many2many_tags"/>
</group>
</xpath>
Once someone selects their POS I want to dynamically reload the employee_ids widget with only those that have access to that POS. Here is my code:
@api.onchange("pos_config_ids")
def _onchange_pos_config_ids(self):
"""
Employee filter logic based on POS Config selections.
NOTES:
- This version intentionally does NOT update the many2many UI.
- It only logs and optionally clears employee_ids.
- You can use 'emp_list' later when generating the report.
RULES:
- No POS selected:
-> employee list unrestricted
- POS selected:
-> Compute union of advanced employees
-> Optionally clear employee_ids so user re-selects appropriate clerks
"""
for wiz in self:
# --------------------------------------------
# CASE 1 — No POS selected
# --------------------------------------------
if not wiz.pos_config_ids:
_logger.info(
"SBC DEBUG — No POS selected → employee list unrestricted"
)
# Optionally clear selected employees:
# wiz.employee_ids = [(5, 0, 0)]
return
# --------------------------------------------
# CASE 2 — POS selected
# --------------------------------------------
employee_ids = set()
for config in wiz.pos_config_ids:
advanced = getattr(config, "advanced_employee_ids", False)
_logger.info(
"SBC DEBUG — POS config %s (%s) advanced_employee_ids = %s",
config.id,
config.display_name,
list(advanced.ids) if advanced else "NO FIELD",
)
if advanced:
employee_ids.update(advanced.ids)
emp_list = sorted(employee_ids)
_logger.info(
"SBC DEBUG — Relevant Employees for selected POS configs: %s",
emp_list,
)
# Optional: Clear selected employees so user reselects
wiz.employee_ids = [(5, 0, 0)]
# NOTE:
# Not updating allowed choices anymore.
# Not returning a dynamic domain.
# emp_list is available for use by the report logic.
return
I can clearly see in the logs that the employee_ids is returned as what I want it to be. If I set the employee_ids = emp_list then it will set the employees in tags, but the available list of employees to select from is not ever updated or reduced to only the ones I want available for the user to select.
Is dynamic updating of the options available in the many2many_tags widget just not possible? Is there something I am missing?