#26265: RendererMixin id_for_label causes HTML id uniqueness violation
----------------------------+--------------------
Reporter: scoenye | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 1.9
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+--------------------
When rendering a ChoiceField RadioSelect widget using form.as_p, the
result is
{{{
<ul id="id_field-field">
<li><label for="id_field-field_0">
<input id="id_field-field_0" type="radio" value="1" name="field-
field">
...
</label>
</li>
<li><label for="id_field-field_1">...
</li>
...
</ul>
}}}
Note that the id attribute of the ul element is id_field-field
When rendering the same RadioSelect field manually using
{{{
<ul id="{{field.id_for_label}}">
{% for choice in field %}
<li><label for="{{ choice.id_for_label }}">{{ choice.tag }}</li>
{% endfor %}
</ul>
}}}
the result is
{{{
<ul id="id_field-field_0">
<li><label for="id_field-field_0">
<input id="id_field-field_0" type="radio" value="1" name="field-
field">
</label>
</li>
<li>...
...
</ul>
}}}
The outer ul element id now has the same id as the first radio button.
This should not be.
The problem is caused by the implementation of id_for_label in
forms.widgets.RendererMixin
{{{
def id_for_label(self, id_):
# Widgets using this RendererMixin are made of a collection of
# subwidgets, each with their own <label>, and distinct ID.
# The IDs are made distinct by y "_X" suffix, where X is the zero-
based
# index of the choice field. Thus, the label for the main widget
should
# reference the first subwidget, hence the "_0" suffix.
if id_:
id_ += '_0'
return id_
}}}
vs. what widgets.ChoiceFieldRenderer.render() does:
{{{
id_ = self.attrs.get('id')
...
return format_html(self.outer_html,
id_attr=format_html(' id="{}"', id_) if id_
else '',
content=mark_safe('\n'.join(output)))
}}}
The docs
[https://docs.djangoproject.com/en/1.9/ref/forms/widgets/#django.forms.RadioSelect]
state
The outer <ul> container will receive the id attribute defined on the
widget.
which makes me believe render() is correct. Either way, I think these
should be consistent with each other. If not, then the docs should mention
using the "name" attribute to avoid the id collision.
--
Ticket URL: <https://code.djangoproject.com/ticket/26265>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/050.c5c5819b09fc5f5c39d2c546ee192047%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.