django bootstrap modal form closes on invalid form data - django

I am working on django + bootstrap modal where I am rendering ModelForm to the modal dialog.
The problem which I am facing is the modal form closes as soon as I click on submit button, it's showing errors on the modal form but it closes and the errors can be seen when the modal dialog is opened again.
I am not using any javascript or jquery, I am simply using html tag and handling post in the django view.
Please let me know what can be done to stop closing the dialog if the form is invalid.
modaldialog_modelform.html:
this file contain the code of the modal dialog with form which is rendered from view.
<div class="modal fade in" id="NewRecordModalForm" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h3 class="modal-title" id="myModalLabel">Add New Transport</h3>
</div>
<div class="modal-body">
<form action="" method="post">{% csrf_token %}
{% if form.errors %}<p class="form_field_error">Please correct the following fields</p>{% endif %}
{{ form|crispy }}
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<input type="submit" alt="Add Transport" value="Add Transport" class="btn btn-primary" />
</div>
</div>
</div>
</div>
the above dialog is called from transport.html with below code:
<a class="btn btn-primary btn-xs" data-toggle="modal" data-target="#NewRecordModalForm" data-backdrop="static">
<i class="fa fa-plus"></i>
</a>

Seems page simply reloading and it's reloading in both cases ... you need ajax request (javaScript code) to your server by clicking on submit button, simplest way to do it using jQuery jQuery AJAX submit form

Related

Trigger a flask WTF SubmitField from a bootstrap 5 modal button

I have created a flask form, embedded in a bootstrap 5 modal. The modal looks like this:
When I click "Weiter" I want to be able to both move to the next modal, and validate and collect the data from the form in my flask form. I can't work out how to create this action with the flask WTF SubmitField. Here is my modal:
<div class="modal fade" id="Modal_1_Toggle" aria-hidden="true" aria-labelledby="Modal_1_ToggleLabel" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="Modal_1_ToggleLabel">Stufe 1</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form method="POST" enctype="multipart/form-data">
{{ form_1.csrf_token }}
<p>
{{ form_1.optimise_option.label(class="form-label") }}
{{ form_1.optimise_option(class="form-select form-select-sm") }}
</p>
{{ form_1.submit(class="btn btn-primary") }} <--- THIS IS WHERE I WANT TO TRIGGER THE NEXT MODAL AND RETURN THE FORM DATA
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" data-bs-target="#Modal_2_Toggle" data-bs-toggle="modal" data-bs-dismiss="modal">Weiter</button>
^^THIS IS THE BOOSTRAP BUTTON, IDEALLY THIS WOULD BE MY SUBMITFIELD BUTTON
</div>
</div>
</div>
</div>
I thought I might be able pass the bootstrap css variables from the bootstrap button directly to the SubmitField as arguments like this:
{{ form_1.submit(class="btn btn-primary" data-bs-target="#Modal_2_Toggle" data-bs-toggle="modal" data-bs-dismiss="modal") }}
But it seems this is not possible. Any help would be really appreciated.

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"))
});
})

Bootstrap modal to confirm deletion

When I loop over my images I have an icon that you can click to delete the image. Instead I'd like to have a modal pop up to confirm the deletion. The only problem is I don't want to repeate the code for the modal for each image. I need a way to pass the image id to the modal.
I was thinking I could pass the id in through an onClick but I'm not sure that will work with the Bootstrap modal.
Here's how I'm currently deleting:
{% for image in images %}
<img src="{{image.image.url}}">
<form method="POST" action="{% url 'products:delete_image>
{% csrf_token %}
<button type="submit" rel="tooltip" title="Remove">
<i class="material-icons">close</i>
</button>
</form>
{% endfor %}
Here's the modal code I'd like to integrate
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter">
Launch demo modal
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
Assign a click handler to the button inside each form and give each form a unique id. For example, give all the form buttons a class like confirm-delete. Assign a click handler (this is jQuery but you could also use vanilla JS)...
$('.confirm-delete').on('click', function(e) {
// prevent form submit
e.preventDefault();
// get the current image/form id
var id = $(this).attr("id")
// assign the current id to the modal and show the modal
$('#myModal').data('id', id).modal('show');
})
Then inside the modal, have a button that actually performs the delete using the id that is passed through data...
$('#btnDelete').click(function() {
// handle deletion here
var id = $('#myModal').data('id');
// submit the form
$('form'+id).submit();
// if needed, remove deleted image
// and form from DOM
$('#img'+id).remove();
$('#form'+id).remove();
// hide modal
$('#myModal').modal('hide');
})
Demo

connecting button to modal with bootstrap

I need some help connecting a button which pops up a modal to submit form.
this is my html before the modal (works fine and another page is rendered after button is clicked)
<div class="container my-container">
<h3>
Let's get started
</h3>
<div class="row my-row">
<h4>1. CSV file</h4>
</div>
<div class="row my-row">
<h4>2. There should be only two columns</h4>
</div>
<div class="row my-row">
<form method="post" enctype="multipart/form-data">
{%csrf_token%}
<input type="file" name="document"><br>
<button type="submit"> Submit</button>
</form>
</div>
</div>
I have added the modal but I now have a couple of issues
<div class="container my-container">
<div class="row my-row">
<h3>
Let's get started
</h3>
</div>
<div class="modal fade" id="demo123">
<div class="modal-dialog">
<div class="modal-content">
<button type="button" class="close" data-dismiss="modal">
<span>
×
</span>
</button>
<div class="modal-header">
<h2 class="modal-title">
Confirm upload
</h2>
</div>
<div class="modal-body">
<p>this is the file name</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">
Confirm
</button>
</div>
</div>
</div>
</div>
<div class="row my-row">
<h4>1. CSV file</h4>
</div>
<div class="row my-row">
<h4>2. There should be only two columns titled</h4>
</div>
<div class="row my-row">
<form method="post" enctype="multipart/form-data">
{%csrf_token%}
<input type="file" name="document"><br>
<button class="btn btn-primary" data-toggle="modal" data-target="#demo123">
Submit
</button>
</form>
</div>
</div>
First issue I have is the "submit" button automatically makes the upload(renders to another page). How can I make so only if "confirm" button is the one which actually submits the form (if "x" then pop-up closes). Also how can I display the filename in the pop-up?
I use django with bootstrap 4
You have to use Javascript and since Bootstrap uses jQuery, you'll have to create that logic using Javascript and jQuery.
Handle the dialog confirm button click and only then trigger a form submit event.
Handle modal show event show.bs.modal and set the dialog filename element if there is a file selected and enable the confirm button; if there is no file selected, message the user about it using the same filename element and disable the confirm button so the user can't click it.
You can run the code snippet and test the whole functionality. On form submission we cancel the event and print a message in the console just for demonstration.
Please read inline comments
jQuery(function($) {
// Handle form submit.
// This won't be necessary unless you want some custom behavior.
// Here we just cancel the form submission and just display a message for demonstration
$('#uploadForm').on('submit', function(e) {
console.log('The form is submitting; preventing event for demonstration');
e.preventDefault();
});
// Handle dialog confirm button click.
$('#confirmUpload').on('click', function(e) {
// Submit the form and hide the dialog when confirm clicked
$('#demoModal123').modal('hide');
$('#uploadForm').submit();
});
// When the dialog is about to show, check if the user has selected a file.
// If they have, update dialog filename element and enabled the confirm button,
// else message user that there is no file and disable the confirm button
$('#demoModal123').on('show.bs.modal', function() {
let files = document.getElementById('documentFile').files;
let fileSelected = files && files[0];
if (fileSelected) {
$('#demoModal123 .filename').text(fileSelected.name);
$('#confirmUpload').prop('disabled', false);
} else {
$('#demoModal123 .filename').text('No file selected');
$('#confirmUpload').prop('disabled', true);
}
});
// Update file input group control label on file selection
$('#documentFile').on('change', function() {
$('#documentFileName').text(this.files[0].name);
});
});
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<div class="container my-container">
<h3>Let's get started</h3>
<div class="row my-row">
<h4>1. CSV file</h4>
</div>
<div class="row my-row">
<h4>2. There should be only two columns</h4>
</div>
<div class="row my-row">
<form method="post" enctype="multipart/form-data" id="uploadForm">
<!-- {%csrf_token%} -->
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroupFileAddon01">Upload</span>
</div>
<div class="custom-file">
<input type="file" class="custom-file-input" name="documentFile" id="documentFile">
<label class="custom-file-label" id="documentFileName" for="documentFile">Choose file</label>
</div>
</div>
<button class="btn btn-primary" type="button" data-toggle="modal" data-target="#demoModal123">Submit</button>
</form>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="demoModal123">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="exampleModalLabel">Confirm upload</h2>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p class="filename">this is the file name</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="confirmUpload">Confirm</button>
</div>
</div>
</div>
</div>
To be able to act Confirm button as only submission, you'll have to add type="submit" in Confirm button and type="button" in Submit button. Like this:
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#demo123">
Submit
</button>
<button type="submit" class="btn btn-secondary" data-dismiss="modal">
Confirm
</button>

Map Bootstrap modal button to Flask WTF submit

I have rendered a form in my Flask web app. For my specific use case, I would like to add a modal dialog window to "confirm" the user's choice. I can get the modal to display, but I can't figure out how to map the "confirm" button (in the modal) to the form action. The examples on the bootstrap docs do not include button mapping in the examples.
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
<unrelated content>
...
</unrelated content>
...
<h4>Enter the email address of the employee receiving the unit</h4>
<div class="col-lg-3">
<div class="row">
<form class="form" id="emailForm" action="{{ url_for('main.transfer', serial=system.serial) }}" method="POST">
{{ mail_form.hidden_tag() }}
{{ mail_form.email }}
{{ mail_form.submit }}<!-- ###THIS IS WHAT I WANT THE MODAL CONFIRM TO TRIGGER -->
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Transfer
</button>
</form>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Unit Transfer</h5>
<!--<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>-->
</div>
<div class="modal-body">
You are transferring a unit from {{ system.assignee.email }} to another user. Are you sure?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-success success" type="submit" data-target="#emailForm.submit()">Confirm</button>
</div>
</div>
</div>
</div>
How do I tell the modal what I want to happen when the Submit button is clicked? All the documentation I can find talks about putting the entire form inside the modal, and that's not what I want.
Thanks in advance.
Make the following changes,
Change {{ mail_form.submit }} to {{ mail_form.submit(hidden='true', id='form-submit') }} to make the submit button hidden.
Change <button type="button" class="btn btn-success success" type="submit" data-target="#emailForm.submit()">Confirm</button> to <button type="button" class="btn btn-success success" id="modal-confirm">Confirm</button>
Add the below script after adding the jquery ,
<script>
$('#modal-confirm').click(function(){
// Perform the action after modal confirm button is clicked.
$('#form-submit').click(); // submitting the form
});
</script>
I hope this helps.