Reputation: 905
I have a form in Django which is embedded in a bootstrap modal element. The input of the form is a client id which I check if it is in the database. Everything works fine on submit except that in case the client id is not in the database the page gets reloaded and I have to open the modal element again to see the error message.
I tried to simple prevent the page refresh by adding a script to my html:
$('#modalform').on('submit', function (e) {
e.preventDefault();
})
But this breaks the form behaviour on submit.
The modal div with the form in my home.html looks like this:
<div class="modal fade" tabindex="-1" role="dialog" id="mymodal" aria-labelledby="myLargeModalLabel">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form action="" method="POST" id="modalform">
{% csrf_token %}
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
</div>
{% endif %}
{% for field in form.visible_fields %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
</div>
{% endfor %}
<input class="btn btn-primary" type="submit" value="submit">
</form>
</div>
</div>
</div>
The view in view.py looks like this:
def home(request):
if request.method == "POST":
print("POST")
form = SelectClient(request.POST)
if form.is_valid():
url = reverse(
"client",
kwargs={"client_id": form.cleaned_data["client_id"]},
)
return HttpResponseRedirect(url)
else:
form = SelectClient()
print("GET")
return render(request, "app/home.html", {"form": form})
The form looks like this:
class SelectClient(forms.Form):
client_id = forms.CharField(label="Client ID")
def clean_client_id(self):
data = self.cleaned_data["client_id"]
if Client.objects.filter(client_id=data).exists():
print("Success!")
else:
print("No such client!")
raise ValidationError(
_("No such client!")
)
return data
And urls.py looks like this:
urlpatterns = [
path("", views.home, name="app-home"),
path(
"client/<str:client_id>",
views.client,
),
]
Can I achieve that on submit of a client_id which is not in the database the page does not fully reload and just updates the error message without using ajax?
If not: How would the added ajax code look like, if I want the desired behaviour?
My first idea went to something like this:
$('#modalform').on('submit', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '/home/',
data: {
client_id: $('#client_id').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function () {
alert("Client found, but what now?!");
},
error: function () {
alert("Client not found, but what now?!")
}
})
})
Upvotes: 0
Views: 3337
Reputation: 905
As I found it hard to work with Django Forms in this case, I solved the problem more explicitly.
My new test_form
form:
<form id="test_form">
{% csrf_token %}
<div class="form-group">
<label for="client_id">Client ID:</label>
<input class="form-control" id="client_id" placeholder="Client ID" />
<div class="form-text text-danger" id="form-error"></div>
</div>
<input class="btn btn-primary" type="submit" value="submit">
</form>
My Javascript for the new test_form
form:
$('#test_form').on('submit', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: 'ajax/testform/',
data: {
client_id: $('#client_id').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
success: function (data) {
console.log(data["status"])
if (data["status"] == "valid") {
window.location.href = "/client"
}
if (data["status"] == "invalid") {
$("#form-error").html(data["message"]);
$("#client_id").addClass("is-invalid")
}
},
error: function () {
alert("Error!")
}
})
})
And the new testform
view:
def testform(request):
if request.method == "POST":
form = SelectClient(request.POST)
if request.is_ajax():
if form.is_valid():
data = {"status": "valid", "client_id": form.cleaned_data["client_id"]}
else:
data = {
"status": "invalid",
"client_id": form.data["client_id"],
"message": form.errors["client_id"],
}
else:
data = {"message": "not an ajax call"}
return JsonResponse(data)
Anything against this solution? Is this consider good practice?
Upvotes: 1
Reputation: 5793
You want to check if there are form errors (you could do a specific field) and pop the modal if there are
<script>
{% if form.errors %}
document.getElementById("mymodal").showModal();
{% endif %}
</script>
Upvotes: 1