Code

Opened 8 months ago

Closed 7 months ago

#20931 closed Bug (fixed)

RadioSelect, RadioSelectMultiple, CheckBoxSelect, CheckBoxSelectMultiple do not render nested option sets correctly

Reported by: dyve Owned by: cbabs
Component: Forms Version: master
Severity: Normal Keywords: choices
Cc: carljm Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The Select widget is the default widget to handle fields that make use of choices. These are commonly rendered as a HTML select, as implemented for django.forms.widgets.Select.

Sometimes a series of radio buttons or checkboxes is a better fir for the UI. Django supports this by implementing widgets that can stand in for Select. These are RadioSelect, RadioSelectMultiple, CheckBoxSelect, CheckBoxSelectMultiple.

The choices to render are implemented as a n iterable of 2-tuples as documented here:
https://docs.djangoproject.com/en/dev/ref/models/fields/#field-choices

As stated in the documentation, choices can be grouped for organizational purposes. The example given:

MEDIA_CHOICES = (
    ('Audio', (
            ('vinyl', 'Vinyl'),
            ('cd', 'CD'),
        )
    ),
    ('Video', (
            ('vhs', 'VHS Tape'),
            ('dvd', 'DVD'),
        )
    ),
    ('unknown', 'Unknown'),
)

When using a Select or SelectMultiple widget, these groups are rendered as HTML optgroup elements. This is correct.

When using any of the other widgets mentioned, the organizational groups are not taken into account when rendering the widget. Instead, the entire group is forced to text without escaping, resulting in a single widget for each group, with the text representation of the list as its label (newlines and spaces added for better readability):

<label for="id_category3_0">
    <input id="id_category3_0" name="category3" placeholder="Category3" title="" type="radio" value="Audio" />
    ((&#39;vinyl&#39;, &#39;Vinyl&#39;), (&#39;cd&#39;, &#39;CD&#39;))
</label>

The solution for this would be take have the renders of these widgets mimic the behavior of Select.render_options, but instead of optgroup an extra level of ul would have to be generated. In pseudo-HTML, for the given example:

<ul>
    <li>
        Audio
            <ul>
                <li>(input element for vinyl</li>
                <li>(input element for CD</li>
            </ul>
    </li>
    ....
</ul>

Attachments (0)

Change History (7)

comment:1 Changed 8 months ago by claudep

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted
  • Version changed from 1.5 to master

comment:2 Changed 8 months ago by carljm

  • Cc carljm added

comment:3 Changed 7 months ago by cbabs

  • Owner changed from nobody to anonymous
  • Status changed from new to assigned

comment:4 Changed 7 months ago by cbabs

  • Owner changed from anonymous to cbabs

comment:5 Changed 7 months ago by cbabs

Cannot find a "RadioSelectMultiple" or "CheckBoxSelect" widget anywhere in Django. Keeping RadioSelect & CheckboxSelectMultiple, but ignoring those two.

comment:6 Changed 7 months ago by cbabs

comment:7 Changed 7 months ago by Julien Phalip <jphalip@…>

  • Resolution set to fixed
  • Status changed from assigned to closed

In a834bc84d8c76d4a7016ac4db4f631a8bcaa3d0b:

Fixed #20931 -- Fixed select widgets nested choice rendering

ChoiceFieldRenderer was not rendering nested choices. Added recursion
to ChoiceFieldRenderer to take nested choices and render them as
<ul>'s.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.