16. Conditional Field and Fieldset Expressions¶
Sometimes it doesn’t make sense to render all fields of a form. Consider for instance a questionnaire of a radiologist, who needs to know if his patient is pregnant. Some male patients might be offended by that question. The most user-friendly solution to this is to hide or disable such a field.
For this purpose django-formset offers three conditionals:
df-show="<condition>"
: The field or fieldset is only shown if the<condition>
evaluates to true.df-hide="<condition>"
: The field or fieldset is only shown if the<condition>
evaluates to false.df-disable="<condition>"
: The field or fieldset is disabled if the<condition>
evaluates to true.
The <condition>
can be any logical JavaScript expression. It can contain comparison operators
such as ==
, <
or !=
and logical operators such as &&
, ||
and !
. This
conditional expression also has access to all the values in the complete context of its own
<django-formset>
. Values from fields in the same form can be accessed using a relative path,
starting with dot, for instance .fieldname
. Values from fields in other forms can be accessed by
specifying the complete path to that field, for instance formname.fieldname
. This also works for
deeply nested forms.
Note
Fields using the conditionals df-show="…"
or df-hide="…"
shall use the attribute
required=False
during initialization. This is because otherwise Django’s form validation
rejects that field as required, meanwhile it has been hidden by the client. In case only visible
fields are required, adopt the validation code of the clean()
-method in the corresponding
form class.
16.1. Questionnaire Form¶
This form uses a conditional where the value of one field influences if another field is visible.
from django.forms import fields, forms, widgets
class QuestionnaireForm(forms.Form):
full_name = fields.CharField(label="Full Name")
gender = fields.ChoiceField(
label="Gender",
choices=[('f', "Female"), ('m', "Male")],
widget=widgets.RadioSelect,
)
pregnant = fields.BooleanField(
label="Are you pregnant?",
required=False,
widget=widgets.CheckboxInput(attrs={'df-show': ".gender=='f'"})
)
Here we add the conditional df-show=".gender=='f'"
to the checkbox asking for pregnancy. Only
if the field gender
contains value f
, then that checkbox is visible. The path for accessing
that variable is relative here: If it starts with a dot, then the named field from the same form is
evaluated.
16.2. Conditional Fieldset¶
Conditionals can also be used on a Fieldset element. For example by using
from django.forms import fields, forms
from formset.collection import FormCollection
from formset.fieldset import Fieldset
class CustomerForm(Fieldset):
legend = "Customer"
hide_condition = 'register.no_customer'
recipient = fields.CharField(label="Recipient")
email = fields.EmailField(label="Email", required=False)
class RegisterForm(forms.Form):
no_customer = fields.BooleanField(
label="I'm not a customer",
required=False,
)
class CustomerCollection(FormCollection):
customer = CustomerForm()
register = RegisterForm()
Here we use the value of the field no_customer
in form RegisterForm
. If it evaluates to
true, the whole fieldset is hidden.
16.3. Conditional Disable¶
Conditionals can also be used to disable other fields. By using the attribute
df-disable=<condition>
we can disable a field, preventing the user to input data.
class AcceptForm(forms.Form):
accept_terms = fields.BooleanField(
label="Accept terms and conditions",
required=False,
)
email = fields.EmailField(
label="Email",
widget=widgets.EmailInput(attrs={'df-disable': ".accept_terms==''"})
)
Here we use the value of the field accept_terms
in form AcceptForm
. If it is unchecked the
email field is disabled.
Please do not mix up the possibility of disabling a field with the functionality to Auto-Disable Buttons, which is part of the form validation process.