django-widget-tweaks icon indicating copy to clipboard operation
django-widget-tweaks copied to clipboard

Rendering of multi-widget fields and subwidgets

Open treyhunner opened this issue 13 years ago • 7 comments

This is a feature request that may become a pull request if I decide to submit code for these features.

I have a modification of render_field that I have been using (as render_multi_field currently) that allows widgets from multi-widget fields to be rendered individually. This allows finer control over the rendering of fields using multi-widgets such as SplitDateTimeWidget.

Another widget type that often requires more control than Django offers by default is the RadioSelect widget which uses RadioInput subwidgets. This widget could be rendered with more control if subwidgets were rendered individually. RadioInput's tag method could be used to render each radio button when looping over them via the subwidgets method.

treyhunner avatar Mar 30 '12 18:03 treyhunner

What does syntax look like?

I think ideally it should be possible to iterate over subwidgets (using standard {% for %} templatetag) and apply django-widget-tweaks tags and filters on a subwidget with the existing syntax.

Currently some django's subwidgets can be iterated (this is slightly improved in 1.4) and some can't.

I started a thread at django-developers ( https://groups.google.com/forum/?fromgroups#!topic/django-developers/yVAmf2DmCrY ) - it is a bit vague though :)

There is also a feature request for customizing field labels (https://bitbucket.org/kmike/django-widget-tweaks/issue/6/not-able-to-add-class-on-label) and a bug report about SelectDateWidget multi-widget (https://bitbucket.org/kmike/django-widget-tweaks/issue/2/doesnt-work-for-selectdatewidget) - they are somewhat related to this.

kmike avatar Mar 30 '12 18:03 kmike

For render_multi_field the syntax I'm currently using is the same as render_field but adds an extra argument for the field index. For example:

{% render_multi_field form.datetime 0 class+="datepicker" %}
{% render_multi_field form.datetime 1 class+="timepicker" %}

Unfortunately implementing a similar tag for RadioSelect seems to require some ugly code repetition from BoundedField.as_widget.

I agree with idea behind that django-developers post. I have copy-pasted sections of code from field and widget classes far too often.

treyhunner avatar Mar 30 '12 19:03 treyhunner

I ran into a similar problem: I was trying to get a MultiWidget to render its subwidgets in two columns using Bootstrap. In order to do this, the output needed to look something like this:

<div class="row">
    <div class="col-xs-6">
        <input type="text" ... >
    </div>
    <div class="col-xs-6">
        <input type="text" ... >
    </div>
</div>

Therefore I came up with the following code which, admittedly, is a rather nasty example of monkey-patching. Bootstrap uses a grid system based on 12 columns, so you could split a row into two columns 6 units wide, three columns 4 units wide, etc.

if isinstance(field.field.widget, forms.MultiWidget):
    def format_output(rendered_widgets):
        width = max(12 / len(rendered_widgets), 3)
        cols = ('<div class="col-xs-%d">%s</div>' % (width, w,) for w in rendered_widgets)
        return '<div class="row">%s</div>' % ''.join(cols)
    field.field.widget.format_output = format_output

The max() ensures that there are no columns smaller than 3 units (and avoids fractional width values). Each instance of MultiWidget has a method named format_output() that controls how the HTML for the widgets are combined. The example above "patches" this method with a custom version that inserts the correct HTML where needed.

The code above is ugly and mixes presentation with code. But hopefully someone finds it useful.

nathan-osman avatar Feb 23 '14 02:02 nathan-osman

Here is a branch containing a widget_tweaks_extras template tag library with two extra tags I cobbled together long ago for rendering multi-widget fields and fields with subwidgets: https://github.com/treyhunner/django-widget-tweaks/tree/multi-widgets

There are no tests in that branch and the code may not be optimally designed. Anyone is welcome to steal from it as you like for your own purposes or for the sake of creating a more robust solution to add to django-widget-tweaks.

treyhunner avatar Mar 12 '14 03:03 treyhunner

@treyhunner that's very useful. Was just about to see how exactly to tackle this, which would have probably involved a custom render method on MultiWidget to return a list instead of a string.

jpadilla avatar Apr 02 '15 16:04 jpadilla

Here is a branch containing a widget_tweaks_extras template tag library with two extra tags I cobbled together long ago for rendering multi-widget fields and fields with subwidgets: https://github.com/treyhunner/django-widget-tweaks/tree/multi-widgets

There are no tests in that branch and the code may not be optimally designed. Anyone is welcome to steal from it as you like for your own purposes or for the sake of creating a more robust solution to add to django-widget-tweaks.

Worked like a charm even 6 years later. This should definitely be a part of the main package.

A4TIF avatar Feb 11 '20 07:02 A4TIF

Remember to accept the code that follows the main: jazzband guideline.

Viability Testing Documentation

And not PR it is made!

zodman avatar Feb 11 '20 15:02 zodman