'HTMX-How can I get valid form when field "keyup changed"
I have a forms.py as following. I am using htmx for validation. And I would like to get whole form for use form.is_valid() function. But in my case I am getting no valid form.
Is there any way to get all form with HTMX?
forms.py
class UniversityForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_id = 'university-form'
self.helper.attrs = {
'hx-post': reverse_lazy('index'),
'hx-target': '#university-form',
'hx-swap': 'outerHTML'
}
self.helper.add_input(Submit('submit', 'Submit'))
subject = forms.ChoiceField(
choices=User.Subjects.choices,
widget=forms.Select(attrs={
'hx-get': reverse_lazy('check-subject'),
'hx-target': '#div_id_subject',
'hx-trigger': 'change'
})
)
date_of_birth = forms.DateField(widget=forms.DateInput(attrs={'type': 'date', 'max': datetime.now().date()}))
class Meta:
model = User
fields = ('username', 'password', 'date_of_birth', 'subject')
widgets = {
'password': forms.PasswordInput(),
'username': forms.TextInput(attrs={
'hx-get': reverse_lazy('check-username'),
'hx-target': '#div_id_username',
'hx-trigger': 'keyup[target.value.length > 3]'
})
}
def clean_username(self):
username = self.cleaned_data['username']
if len(username) <= 3:
raise forms.ValidationError("Username is too short")
return username
def clean_subject(self):
subject = self.cleaned_data['subject']
if User.objects.filter(subject=subject).count() > 3:
raise forms.ValidationError("There are no spaces on this course")
return subject
def save(self, commit=True):
""" Hash user's password on save """
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
views.py
def check_username(request):
form = UniversityForm(request.GET)
if form.is_valid():
print('Valid')
else:
print('No Valid')
print(form.errors)
print(form['date_of_birth'])
context = {
'field': as_crispy_field(form['username']),
'valid': not form['username'].errors
}
return render(request, 'partials/field.html', context)
Error: Even all fields are filled; my output of >print('No Valid') >print(form.errors) >print(form['date_of_birth']) are as following...
No Valid
<ul class="errorlist"><li>password<ul class="errorlist"><li>This field is required.</li></ul></li><li>date_of_birth<ul class="errorlist"><li>This field is required.</li></ul></li><li>subject<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
<input type="date" name="date_of_birth" max="2022-03-15" required id="id_date_of_birth">
Solution 1:[1]
The username checking HTMX GET request is activated only on the username field. By default HTMX will not include any other parent element in the request, this is the reason of the missing fields error message.
To include other elements in the request, you can use the hx-include attribute, where you list the additional fields' CSS query selector:
class Meta:
model = User
fields = ('username', 'password', 'date_of_birth', 'subject')
widgets = {
'password': forms.PasswordInput(),
'username': forms.TextInput(attrs={
'hx-get': reverse_lazy('check-username'),
'hx-target': '#div_id_username',
'hx-trigger': 'keyup[target.value.length > 3]',
'hx-include': '[name="password"],[name="date_of_birth"],[name="subject"]'
})
}
Note: in the POST request you don't have to use this, because you put the HTMX attribute on the outermost form element, so by default HTMX will include each field (child elements of the form) in the request.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
