Bootstrap modal form disappears when submitted with errors - bootstrap-modal

I've just converted a form to a Bootstrap modal and it works fine except when submitted with errors the modal just disappears. Clicking on the modal trigger button brings the modal back up with the user's data and error messages.
Here's my code:
<div class="modal fade" id="myModal" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form method='POST' action=''>
{% csrf_token %}
{{ form.as_p }}
<input id='submit-button' type="submit" value="Submit">
</form>
</div> <!-- modal-body -->
</div>
</div>
</div>
<button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">Apply now</button>
I'm using Django but I don't think that's got anything to do with it because everything worked until I wrapped the form in a modal. Here's my view.py:
def homepage(request):
form = MyForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
return HttpResponseRedirect(reverse('success'))
context = {
"form": form,
}
return render(request, 'home.html', context)
Can someone tell me what I'm doing wrong?

After submit there is no information about modal, it's hidden like on the first time when you open the page. You can add some condition to open modal if there is an error.
I don't know Django, but the idea is to add some param to model:
if (bindingResult.hasErrors()) {
model.addAttribute("formErrors", true);
}
And then check (I use Thymeleaf in this example):
<th:block th:if="${formErrors}">
<script>$('#myModal').modal('show');</script>
</th:block>

Related

Flask Modal Confirm Dialog

I am trying to add a modal dialog to confirm the user's comment. After user finishes editing title and comment then clicks submit button, a modal dialog will pop up for user to confirm. How can I get the data from html after user clicks confirm button on modal?
form.py
class PostForm(FlaskForm):
title_field = StringField('Title')
comment_field = TextAreaField('Comment')
submit = SubmitField('Update')
routes.py
#posts.route('/update_post/<post_id>', methods=['GET', 'POST'])
def post(post_id):
form = PostForm()
post= Post.query.get_or_404(post_id)
if request.method == 'POST':
print(form.title_field.data)
print(form.comment_field.data)
return redirect(url_for('posts.post'))
return render_template('post.html', title='Post', form=form, post=post)
post.html
<!-- form-->
<form action= "" method="POST", enctype="multipart/form-data">
{{ form.hidden_tag() }}
<p></p>
<h4>New Post</h4>
<div class="form-group">
{{ form.title_field.label(class="form-control-label") }}
{{ form.title_field(class="form-control form-control-lg") }} <!-- Pass this data> -->
</div>
<div class="form-group">
{{ form.comment_field.label(class="form-control-label") }}
{{ form.comment_field(class="form-control form-control-lg") }} <!-- Pass this data> -->
</div>
{{ form.submit( class="btn btn-outline-info", data_toggle="modal", data_target="#updateModal") }}
</form>
<!-- Modal -->
<div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateModalLabel">New Post?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<form action="{{ url_for('post.post', post_id=post.id) }}" method="POST">
<input class="btn btn-success" type="submit" value="Confirm">
</form>
</div>
</div>
</div>
</div>
#NoCommandLine Thanks for the help
This is the final solution I have come out
Change form.submit to a button
<button type="button" class="btn btn-outline-info" data-toggle="modal" data-target="#updateModal">Update</button>
Add onclick for modal button
<button type="button" class="btn btn-success" id="btnConfirm" onclick="form_submit()">Confirm</button>
Add Javascript
function form_submit(){
// Close the Modal
$("#updateModal").modal("hide");
// submit it
document.getElementById("mainForm").submit();
}
I would approach this a different way
Remove the form in the modal and just have a normal button with an id e.g. id="btnConfirm".
Give your main form an id e.g.
<form action= "" method="POST", enctype="multipart/form-data" id="mainForm">
When user clicks on the button (confirm), use Javascript to close the modal, and then submit your main form. Sample code (note - this is untested sample code; it might have some bugs)
$("#btnConfirm").on("click", function(){
// Close the Modal
$("#updateModal").modal("hide");
// Get the contents of the main form and submit it
fetch(<URL>, {
method:'POST',
body: new FormData($("#mainForm"))
});
})

passing instance to Django modal form

I want to do edit on a modal pop up form, edit is working but cant see the existing instance, how I can do it? any help is appreciated.
Here I have passed the form as below
class DomainListView(ListView):
model = Domain
template_name = 'super_admin/domain_list.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
form = DomainEditForm(self.request.POST or None)
context['form'] = form
return context
and the template is as follows
<div class="modal fade" id="domain-edit-{{ item.pk }}">
<div class="modal-dialog" role="document">
<form class="form-valide" action="{% url 'domain_edit' item.pk %}" method="POST" id=""
enctype="multipart/form-data">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"> Edit Domain </h5>
<button type="button" class="close" data-dismiss="modal"><span>×</span>
</button>
</div>
<div class="modal-body">
<div class="basic-form">
<div class="form-group">
{% csrf_token %}
{{ form.errors }}
{{ form | crispy }}
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">submit</button>
</div>
</div>
</form>
</div>
</div>
this is inside for loop along with list items, I tried to fetch the instance as follows in get context data override, but it gives key error
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
obj = get_object_or_404(Domain, kwargs={'pk': self.kwargs['pk']})
form = DomainEditForm(self.request.POST or None, instance=obj)
context['form'] = form
return context

form is not saving changes in dialog modal (popup) Django

I’m really new in Django.
I’m trying to implement Modal dialog using forms. The problem is that even when I make some changes in my form, this changes are not shown in database… I have no idea why. When I test form outside Modal dialog, form is working…
Here is my form.py:
class anomalie_location_form(ModelForm):
class Meta:
model = Anomalie
fields = ['localization', ]
here is my view.py
#login_required(login_url='login')
def fix_anomalie_stock(request, pk, type_anomalie):
anomalie_pk = Anomalie.objects.get(id=pk)
# form to change anomalie position
form_location = anomalie_location_form(instance=anomalie_pk)
if request.method == 'POST':
print('printinng anomalie_location_form POST ', request.POST)
form_location = anomalie_location_form(
request.POST, instance=anomalie_pk)
if form_location.is_valid():
form_location.save()
return redirect('/')
context = {'anomalie_pk': anomalie_pk,
'form_location': form_location}
return render(request, "anomalie/fix_anomalie_stock.html", context)
and my html:
<div class="modal fade" id="myModal2" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4>{{product.product_name }}</h4>
</div>
<form action="" method="POST">
{% csrf_token %}
<div class="modal-body">
{{form_location}}
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Treter" data-dismiss="modal">
</div>
</form>
</div>
</div>
</div>
this is the model.py
class Anomalie (models.Model):
ANOMALIE = (
("Etiquette absente", "Etiquette absente"),
("Etiquette decalee", "Etiquette decalee"),
("Etiquette inconnue", "Etiquette inconnue"),
)
ANOMALIE_STATE = (
("traité", "traité"),
("mise à jour", "mise à jour"),
("signalé", "signalé"),
)
type = models.CharField(
max_length=200, choices=ANOMALIE, null=False)
date_report = models.DateTimeField(null=False, blank=False)
localization = models.TextField(max_length=30, null=False, blank=False)
state = models.CharField(
max_length=200, choices=ANOMALIE_STATE, null=False)
aisle = models.ForeignKey(Aisle, null=True, on_delete=models.SET_NULL)
product = models.ForeignKey(
Product, null=True, on_delete=models.SET_NULL)
def datepublished(self):
return self.date_report.strftime('%B %d %Y')
def __str__(self):
return self.type
and this is the url.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', home_screen_view, name="home"),
path('consult/<str:pk>/', consult_anomalie, name="consult_anomalie"),
path('fix_anomalie_stock/<str:pk>/<str:type_anomalie>',
fix_anomalie_stock, name="fix_anomalie_stock"),
]
So the question is why form is working outside of Dialog Modal ?
The mistake is simple.
That is, the form in the modal have a submit button. This button has the bootstrap modal data-dismiss attribute which makes the modal to dismiss and not the form to submit.
<input type="submit" class="btn btn-primary" value="Treter" data-dismiss="modal">
Remove the bootstrap data-dismiss attribute from submit button.
<input type="submit" class="btn btn-primary" value="Treter">
Code snippet in action
Run the code snippet to see it in action. I've added the modal code from the question. Form submit() to alert the form data and 'hidden.bs.modal' to alert when modal closes. For demo purpose, form has two submit buttons. One with the data-dismiss attribute and the other without. You can see that the button (2) alerts the data while the other closes the modal
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal2">
Launch modal
</button>
<div class="modal fade" id="myModal2" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4>Product Name</h4>
</div>
<form action="" method="POST">
<div class="modal-body">
<input type="text" name="product" class="form-control">
(1) submit button with data-dismiss attribute<br>
(2) submit button without data-dismiss attribute
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="(1) Treter" data-dismiss="modal"> | <input type="submit" class="btn btn-primary" value="(2) Treter">
</div>
</form>
</div>
</div>
</div>
<script>
$(document).ready(function() {
console.log('start');
$('form').submit(function() {
alert($(this).serialize());
})
$('#myModal2').on('hidden.bs.modal', function (e) {
alert('modal closes');
})
});
</script>
I'm missing some details but forms often don't submit properly when inputs are not named. Even your select elements need name and value pair parameters. Have you double checked this?
What can happen with bootstrap is that the modal can confuse the form action. You have it now set to = "". Try removing the action parameter and give your form a unique id.
if request.method == 'POST':
Also try checking if submit button was posted rather than just the request method.
Modal should be inside the form tag and not the other way around.
<form action="" method="POST">{% csrf_token %}
<div class="modal fade" id="myModal2" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4>{{product.product_name }}</h4>
</div>
<div class="modal-body">
{{form_location}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</form>

Using Bootstrap Model with Django classed based views to implement login function

I have created loginview using class-based view concept as following:
class LoginView(NextUrlMixin,RequestformattachMixin,FormView):
form_class = login_page
template_name = 'login.html'
success_url = '/'
def form_valid(self, form):
next_url=self.get_next_url()
return redirect(next_url)
def form_invalid(self, form):
return super().form_invalid(form)
forms.py:
class login_page(forms.Form):
Email = forms.EmailField(required=True,widget=forms.EmailInput(
attrs={"class": "form-control", "placeholder": "Email
address", "id": "exampleInputEmail2"}))
Password = forms.CharField(required=True,widget=forms.PasswordInput(attrs={"class": "form-control",'id':'exampleInputPassword2',
"placeholder": "Password"}))
I have modified on my login.html page to use bootstrap modal as the following:
{% block content %}
<div id="loginModal" class="modal fade">
<div class="loginModal-content">
<div class="loginModal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Login</h4> </div><div class="loginModal-body">
<div class="row">
<div class="col-md-12"> via <div class="social-buttons">
<i class="fa fa-facebook"></i> Facebook
<i class="fa fa-twitter"></i> Twitter
</div>or
<form class="form" role="form" method="post" action="login" accept-charset="UTF-8" id="login-nav">
<div class="form-group">
<label class="sr-only" for="exampleInputEmail2">Email address</label>
{# <input type="email" class="form-control" id="exampleInputEmail2" placeholder="Email address" required>#}
{# {{ form.Email }}#}
</div>
<div class="form-group">
<label class="sr-only" for="exampleInputPassword2">Password</label>
{# <input type="password" class="form-control" id="exampleInputPassword2" placeholder="Password" required>#}
{# {{ form.Password }}#}
<div class="help-block text-right">
Forgot the password ?
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">Sign in</button>
</div>
<div class="checkbox">
<label>
<input type="checkbox"> keep me logged-in
</label>
{{ form }}
</div>
</form>
</div>
<div class="bottom text-center"> New here ?
<b>Join Us</b> </div></div></div>
<div class="loginModal-footer">
</div>
</div>
</div>
{% endblock %}
As I am a newbie in Django, could you please help me how to use the bootstrap modal with my Django CBV
or even how to start as when I started using the Modal it is failed to appear, should I use ajax or what are other technologies should I use. please help from where could i start
Ok, the best way to render fields in django is django-widget-tweaks, this very simple and render all the error and fields with adding classes to that field.
Follow the installation of it - https://github.com/jazzband/django-widget-tweaks
here is simple and full guide of using django-widget-tweaks
I always suggest to use it, hope it will help you.
The plugin I wrote could be your starting point django-bootstrap-modal-forms. If you check the examples project you will also find a fully functional Login and Signup form in modals. You will be able to bind any form to the modal and all of the validation stuff will work out of the box.
You will create a trigger element opening the modal
Your selected form will be appended to the opened modal
On submit the form will be POSTed via AJAX request to form's URL
Unsuccessful POST request will return errors, which will be shown under form fields in modal
Successful POST request will redirects to selected success URL

how to render a djangoform into bootstrap modal window

I am strating to learn Django and I want to display some forms in bootstrap modal view.
I have a template with a HTML table, this table have a column with a drop down button with several options.
the table is rendered with django-tables2 and the forms are rendered with django-crispy-forms
My form definition for the modal form:
class RecepcionForm(forms.ModelForm):
fecha_recepcion = forms.DateField(widget=DateInput())
def __init__(self,*args,**kwargs):
super(RecepcionForm,self).__init__(*args,**kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Field('id_proveedor',
'anio',
'mes',
'usuario',
readonly = True
),
Fieldset('',
'fecha_recepcion',
'num_archivos',
Submit('save','Grabar'),
HTML('<a class="btn btn-danger" href={% url "monitor" %}>Cancelar</a>')
)
)
class Meta:
model = DetalleRecepcion
My view for the modal form:
#login_required(login_url='/login/')
def RecepModalView(request):
idp = request.GET.get('i')
anio = request.GET.get('a')
mes = request.GET.get('m')
if request.method == 'POST':
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
form = RecepcionForm(request.POST, instance=r)
if form.is_valid():
form.save()
return HttpResponseRedirect('/monitor/')
else:
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
r.usuario = request.user
form = RecepcionForm(instance=r)
return render_to_response('recepmodal.html',
{'form':form},
context_instance=RequestContext(request))
My template for the modal form
{% load crispy_forms_tags %}
<div class="modal fade" id="recmodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">Register </h4>
</div>
<div class="modal-body">
<form action="" method=post">
<div class="tab-content">
<div class="tab-pane active" id="tab1">
{% crispy form %}
</div>
</form>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
</div>
I don't know how to open and pass arguments to the modal form.
I try using the django tag include
Example snippet:
<body>
<table>
.
.
.
</table>
{% include 'recmodal.html' %}
</body>
but I get this error
Exception Value: Failed lookup for key [form] in
In simple word how can I pass values and open a bootstrap modal form in django using django-crispy-forms.
Any advice
Thansk in advance
I know it's too late to answer, but I render my forms in a modal using this into a "modal-body" tag:
<form method="post">
{% csrf_token %}
{% form.as_p %}
</form>
I hope this work for all people like me that we came here finding an answer.
Regards.