#28176: Expose real (i.e. not converted to string) value in widget option 
context
------------------------------------------+------------------------
               Reporter:  Moritz Sichert  |          Owner:  nobody
                   Type:  New feature     |         Status:  new
              Component:  Forms           |        Version:  master
               Severity:  Normal          |       Keywords:
           Triage Stage:  Unreviewed      |      Has patch:  0
    Needs documentation:  0               |    Needs tests:  0
Patch needs improvement:  0               |  Easy pickings:  0
                  UI/UX:  0               |
------------------------------------------+------------------------
 In #28075 `option.value` was changed to always be converted to a string
 before passing it to the template. I have a use case that doesn't work
 anymore because of this. I have this form:

 {{{#!python
 from django.forms import Form, RadioSelect, TypedChoiceField


 CHOICES = [
     (1, 'INFO'),
     (2, 'WARNING'),
     (3, 'SUCCESS'),
     (4, 'DANGER'),
 ]

 CHOICES_DICT = {name: value for value, name in CHOICES}


 class RadioSelectWithIcons(RadioSelect):
     template_name = 'radio_select_with_icons.html'

     def get_context(self, name, value, attrs):
         context = super().get_context(name, value, attrs)
         context['choices'] = CHOICES_DICT
         return context


 class MyForm(Form):
     foo = TypedChoiceField(
         coerce=int,
         choices=CHOICES,
         widget=RadioSelectWithIcons
     )
 }}}

 and the following template (`radio_select_with_icons.html`):

 {{{#!htmldjango
 {% for _, options, _ in widget.optgroups %}
   {% for option in options %}
     <label class="btn btn-default{% if option.selected %} active{% endif
 %}">
       <input type="radio" name="{{ widget.name }}" value="{{ option.value
 }}"{% if option.selected %} checked="checked"{% endif %}>
       {{ option.label }}
       {% if option.value == choices.INFO %}
         <span class="fa fa-info-circle text-info"></span>
       {% elif option.value == choices.WARNING %}
         <span class="fa fa-times-circle text-warning"></span>
       {% elif option.value == choices.SUCCESS %}
         <span class="fa fa-check-circle text-success"></span>
       {% elif option.value == choices.DANGER %}
         <span class="fa fa-exclamation-circle text-danger"></span>
       {% endif %}
     </label>
   {% endfor %}
 {% endfor %}
 }}}
 Now, when I render this form, none of the `<span class="fa ..."></span>`
 are displayed. This is because `option.value` is a string and `choices.X`
 are integers so the equality will obviously always be false.

 I can see two solutions to this that don't involve changing code in
 Django:

 1.: Convert the integers in the `choices` to strings as well. I don't
 think this is a sensible solution since I ''know'' that both values are
 supposed to be integers but instead compare their string representations.
 This also becomes a problem if the string version of the value is
 ambiguous, e.g. translated strings.
 2.: Pass the css classes I use in the `<span>` as context from the widget.
 I also think, that this is a bad approach, because I want to separate
 python code from display logic. This also wouldn't work for more complex
 things that don't change just a css class.


 I think there is a good, simple solution to this:  In
 `ChoiceWidget.create_option()` the returned context should also contain
 the un-stringified value. Maybe even rename the current `value` to
 `str_value` and store the actual value in `value`.

 What do you think?

--
Ticket URL: <https://code.djangoproject.com/ticket/28176>
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.791fb6060b8b7de0d5b02afaa2dddf1c%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to