Nacira Boussoualim
Nacira Boussoualim

Reputation: 3

dynamic form in django using choiceField

I'm building my first web app with django and am having a hard time figuring out how to use dynamic form in order to have different output for different selected choice.

for example, for my measure choice qualitative, I want the form be the same(no extra fields) but if the quantitative value is selected, I want my template to show two more fields(value_min and value_max)

the first option when qualitative value is selected

the second option when quantitative value is selected

thank you for your help...

Upvotes: 0

Views: 657

Answers (3)

Nacira Boussoualim
Nacira Boussoualim

Reputation: 3

thanks @videap and @Rhea for your help... so I figured out how to resolve my problem using the guidance of videap and the post Show and hide dynamically fields in Django form

So the solution was:

for the form :

class NewCriterioForm(forms.ModelForm):
    parent = TreeNodeChoiceField(queryset=Criteria.objects.all())
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        
        self.criteria_CHOICES = [('FunCriteria','FunCriteria'),('nonFunCriteria','nonFunCriteria')]
        self.mesure_CHOICES = (('Quantitative','Quantitative'),('Qualitative','Qualitative'))
        self.fields['parent'].label=''
        self.fields['parent'].required=False
        self.fields['type']= forms.CharField(widget=forms.Select(choices=self.criteria_CHOICES))
        self.fields['mesure']= forms.ChoiceField(choices=self.mesure_CHOICES)
    class Meta:
        model = Criteria
        fields = ('name', 'parent', 'type','slug','description','mesure','value_min','value_max')

        }

for the view :

......
criterion = NewCriterioForm()
    return render(request, 'addCriteria.html', {'criterion': criterion})

and finaly, in the template , I put this code:

              <script>
                function Hide() {
                    if(document.getElementById('id_mesure').options[document.getElementById('id_mesure').selectedIndex].value == "Qualitative") {
                         document.getElementById('id_value_min').style.display = 'none';
                         document.getElementById('id_value_max').style.display = 'none';
                    } else {
                         document.getElementById('id_value_min').style.display = '';
                         document.getElementById('id_value_max').style.display = '';
                    }
                }
                
                window.onload = function() {
                    document.getElementById('id_mesure').onchange = Hide;
                };
                </script>
               
                <div>
                    {{ criterion.name.label_tag }}{{ criterion.name }}
                </div>
                <tr></tr>
                <div>
                    {{ criterion.parent.label_tag }}{{ criterion.parent }}
                </div>
                <div>
                    {{ criterion.type.label_tag }}{{ criterion.type }}
                </div>

                <div>
                  {{ criterion.slug.label_tag }}{{ criterion.slug }}
                 </div>
                 <div>
                  {{ criterion.description.label_tag }}{{ criterion.description }}
                  </div>
                  <div>
                  {{ criterion.mesure.label_tag }}{{ criterion.mesure }}
                  </div>

                <div id="id_value_min">
                {{ criterion.value_min.label_tag }}{{ criterion.value_min }}
                </div>
                  <div id="id_value_max">
                    {{ criterion.value_max.label_tag }}{{ criterion.value_max }}
                 </div>

Upvotes: 0

Rhea
Rhea

Reputation: 644

Forms are rendered on the template before the page load. So, django variables cannot e manipulated by the user.

While rendering your form, django allows you to set classes to the form fields. use them to hide the extra fields.

example value_min = forms.CharField(widget=forms.TextInput(attrs={'class':'hide'}))

you may add a form check while clean

 class MYform(forms.Form):
     #....
     def clean_min_value(self):
       #check here for choice field value
       #return value or blank accordingly

similarly you can add validators to the form to ensure this value is only set if choice is set to quantitative

value_min = forms.CharField(widget=forms.TextInput(attrs={'class':'hide'}), validators=[check_choice])

 def check_choice(Value):
   # validate Value

Upvotes: 0

videap
videap

Reputation: 86

You can't use the django tags for conditions, because it only renders from the backend, so this is a frontend issue. In my implementations I normally use javascript with the following idea:

  • Start with the values min and max not displayed (style.display = "None")
  • AddEventListener (onChange type) to the selector (in your case, Mesure)
  • Check if the condition is met with javascript and change the style.display to block, for example

Upvotes: 1

Related Questions