Yehuda
Yehuda

Reputation: 133

django form field displayed out of order

I have this form and model for a group:

class GroupForm(forms.ModelForm):
    class Meta:
        model = Group
        fields = ('leader', 'description', 'size', 'max_size', 'motto')

        widgets = {
            'size': forms.CheckboxInput(attrs={'id': 'size'}),
            'max_size': forms.TextInput(attrs={'type': 'hidden', 'id': 'maxSize'}),
        }

The creator of the group has an option to check yes for size and on doing so, I used javascript to change the type of max_size to show.

In my create_group.html template:

<script>
    let size = document.getElementById('size')
    let maxSize = document.getElementById('maxSize')
    let checked = false
    
    size.onclick = () => {
        checked = !checked
        if (checked === true) {
            maxSize.type = 'show'
        } else {
            maxSize.type = 'hidden'
        }
        
    }
</script>

Now, this works fine, the only problem is that the fields are displayed out of order.

When the page loads, max_size is false and its field is not displayed. Which is good. However, when the user checks that group has a size, and, subsequently, the max_size has a display of show, the field shows up after the motto field and not in its correct order according to fields = ('leader', 'description', 'size', 'max_size', 'motto').

Furthermore, the max_size field is included inside the motto element itself and not as its own field:

enter image description here

vs. the other fields which are all in their own <p></p>.

Upvotes: 0

Views: 72

Answers (2)

Yehuda
Yehuda

Reputation: 133

If anyone else comes across this issue, it's also possible to just use js and css. Right now, I'm using javascript to see if size is checked and if it is then maxSize.style.display = 'block' vs maxSize.style.display = 'none' if size isn't checked.

Then I had the issue of django's form label still being visible. To fix that I saw an answer on dev.to which you can see for yourself.

My issue now is that I don't know how to add a label that is only visible when the form field is visible.

Upvotes: 0

nigel222
nigel222

Reputation: 8222

I'm guessing that {{form.as_p}} etc. render all the visible fields first, then the hidden ones.

You can explicitly render the fields in the order you want in your template. Rather than hardcoding the order in your template, maybe this (I've never tried this):

FIELD_ORDER = ( ('leader', 'description', 'size', 'max_size', 'motto')
class GroupForm(forms.ModelForm):
    class Meta:
        model = Group
        fields = FIELD_ORDER

Pass to your template a list of fields explicitly in the order you want:

fields_in_order = [ form[x] for x in FIELD_ORDER ]

In the template

{% for field in fields_in_order %}
   {{field}}
{% endfor %}

Or, you can make the hiding of this field something done by JS

Upvotes: 1

Related Questions