'How to do Delete confirmation for a table data with bootstrap Modal in Django?
I'm having a table to show a list of actions in my app. I can delete any action in that table. So, I have added a delete button in every row. This delete button will trigger a 'delete confirmation' bootstrap modal.
<table class="table table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col" class="th-lg">Name</th>
</tr>
</thead>
{% for action in actions_list %}
<tbody>
<tr class="test">
<th scope="row" class="align-middle">{{ forloop.counter }}</th>
<td class="align-middle">
{{action.action_name}}
</td>
<td class="align-middle">
{{action.id}}
</td>
<td>
<div class="row justify-content-end">
<button
id="edit"
type="button"
class="btn btn-sm btn-dark col col-lg-2"
style="color: rgb(255,0,0,0)"
>
<i class="lni-pencil"></i>
</button>
<button
id="trash"
type="button"
class="btn btn-sm btn-dark col col-lg-2"
style="color: rgb(255,0,0,0)"
data-toggle="modal"
data-target="#modalConfirmDelete"
>
<i class="lni-trash"></i>
</button>
</div>
</td>
</tr>
</tbody>
{% endfor %}
</table>
Below is the code for 'Delete Confirmation' bootstrap modal. It will have 'Yes' and 'No' buttons. If I click 'Yes', then that particular action id will be passed to URL and that particular action id will be deleted.
{% block modalcontent %}
<!--Modal: modalConfirmDelete-->
<div
class="modal fade"
id="modalConfirmDelete"
tabindex="-1"
role="dialog"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-sm modal-notify modal-danger" role="document">
<!--Content-->
<div class="modal-content text-center">
<!--Header-->
<div class="modal-header d-flex justify-content-center">
<p class="heading">Are you sure?</p>
</div>
<!--Body-->
<div class="modal-body">
<i class="fas fa-times fa-4x animated rotateIn"></i>
</div>
<!--Footer-->
<div class="modal-footer flex-center">
<form action="{% url 'delete_action' aid=action.id %}">
{% csrf_token %}
<button class="btn btn-outline-danger">Yes</button>
</form>
<a
type="button"
class="btn btn-danger waves-effect"
data-dismiss="modal"
>No</a
>
</div>
</div>
<!--/.Content-->
</div>
</div>
{% endblock %}
In above code, I'm using a form tag for the delete action then that action id URL will trigger.
Below is the URL to delete an action,
re_path(r'^delete_action/(?P<aid>\d+)/',
views.delete_action, name='delete_action')
Problem I'm Facing : I need action.id value in the modal which I'm not getting!
Please help me to solve this. thanks in advance :)
Solution 1:[1]
If any of you are going through this scenario, I have a quick fix.
The main idea is to change the form's action URL using Javascript
views.py
class DeleteAddressView(DeleteView):
success_url = reverse_lazy("home")
I will try to provide the minimum solution here:
my link in the list for delete item will be:
<a
href="{% url 'item-delete' item.id %}"
class="dropdown-item text-danger"
data-toggle="modal"
data-target="#delete-item-modal"
id="delete-item"
>
Remove
</a>
modal that popup will be:
<div class="modal fade" id="delete-item-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p>Are you sure, You want to remove this item?</p>
</div>
<div class="justify-content-between mb-2 mr-2 text-right">
<form method="post"
id="item-delete-form"
>
<button type="button" class="btn btn-secondary mr-1" data-dismiss="modal">Cancel</button>
{% csrf_token %}
<button type="submit" class="btn btn-danger" id="confirm-delete-item-button">Delete</button>
</form>
</div>
</div>
</div>
</div>
Now we have to change the form action URL with the item's a href value
<script>
$(document).on('click', '#delete-item', () => {
document.getElementById("item-delete-form").action = document.querySelector('#delete-item').href
});
</script>
I know this is too late for your question but can be helpful for others. This is the easiest way to remove an item from the list without redirecting the page to the confirmation page.
NOTE: frontend framework bootstrap is used to display the modal, so you must check if bootstrap is working or not before continuing with this solution.
Solution 2:[2]
For more explanation on Gorkali's answer, you can check here: https://elennion.wordpress.com/2018/10/08/bootstrap-4-delete-confirmation-modal-for-list-of-items/
This is how is how I solved it, based on the above answer, using plain JavaScript, and adding some more functionality:
in my_template.html:
<a href="{% url 'report_generate' %}"
class="btn btn-primary" id="generate_{{report.id}}"
data-toggle="modal" data-target="#confirmModal"
data-message="If you proceed, the existing report will be overwritten."
data-buttontext="Proceed">
Regenerate
</a>
<a href="{% url 'report_generate'"
class="btn btn-primary" id="finalize_{{report.id}}"
data-toggle="modal" data-target="#confirmModal"
data-message="If you proceed, the existing report will be finalized. After that, it can no longer be edited."
data-buttontext="Finalize Report">
Finalize
</a>
{% include "includes/confirm_modal.html" %}
with the include file confirm_modal.html:
<div class="modal fade" id="confirmModal" tabindex="-1" caller-id="" role="dialog" aria-labelledby="confirmModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-body" id="modal-message">
Do you wish to proceed?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" data-dismiss="modal" id="confirmButtonModal">Confirm</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
var buttons = document.querySelectorAll("[data-target='#confirmModal']");
for (const button of buttons) {
button.addEventListener("click", function(event) {
// find the modal and add the caller-id as an attribute
var modal = document.getElementById("confirmModal");
modal.setAttribute("caller-id", this.getAttribute("id"));
// extract texts from calling element and replace the modals texts with it
if ("message" in this.dataset) {
document.getElementById("modal-message").innerHTML = this.dataset.message;
};
if ("buttontext" in this.dataset) {
document.getElementById("confirmButtonModal").innerHTML = this.dataset.buttontext;
};
})
}
document.getElementById("confirmButtonModal").onclick = () => {
// when the Confirm Button in the modal is clicked
var button_clicked = event.target
var caller_id = button_clicked.closest("#confirmModal").getAttribute("caller-id");
var caller = document.getElementById(caller_id);
// open the url that was specified for the caller
window.location = caller.getAttribute("href");
};
});
</script>
Solution 3:[3]
Delete link:
<a href="javascript:void(0)" data-toggle="modal"
class="confirm-delete"
data-url="{% url 'account:delete_address' pk=address.id %}"
data-target="#deleteItemModal"
data-message="Êtes-vous sûr de supprimer l'article ?"
>
<i class="far fa-trash-alt"></i>
<span>Supprimer</span>
</a>
Modal:
<!-- Modal -->
<div id="container_delete">
<div class="modal fade" id="deleteItemModal" tabindex="-1" role="dialog"
aria-labelledby="deleteItemModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document"> </div>
<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>
</div>
<div class="modal-body confirm-delete text-center" >
<div class="alert" id="delete_item_alert"></div>
<div id="modal-message"></div>
<hr>
<form action="" method="post" id="form_confirm_modal">
{% csrf_token %}
<button type="button" class="btn btn-danger" data-dismiss="modal" id="confirmButtonModal">Oui</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Non</button>
</form>
<input type="hidden" id="address_suppress"/>
</div>
</div>
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
let form_confirm = document.querySelector('#form_confirm_modal')
let buttons = document.querySelectorAll("[data-target='#deleteItemModal']");
buttons.forEach(button => {
button.addEventListener("click", () => {
// extract texts from calling element and replace the modals texts with it
if (button.dataset.message) {
document.getElementById("modal-message").innerHTML = button.dataset.message;
}
// extract url from calling element and replace the modals texts with it
if (button.dataset.url) {
form_confirm.action = button.dataset.url;
}
})
});
let confirmModal = document.getElementById("confirmButtonModal")
confirmModal.addEventListener('click', () => {
form_confirm.submit();
});
});
</script>
Views:
class DeleteAddressView(DeleteView, SuccessMessageMixin):
template_name = 'account/address.html'
success_message = 'Adresse supprimée'
# model = Address
def get_object(self, queryset=None):
_id = int(self.kwargs.get('pk'))
address = get_object_or_404(Address, pk=_id)
return address
def get_success_url(self):
pk = self.request.user.id
return reverse_lazy('account:address', args=(pk,))
Solution 4:[4]
Try this
In your delete link
<a href="{% url 'your-delete-url' pk=your.id %}" class="confirm-delete" title="Delete" data-toggle="modal" data-target="#confirmDeleteModal" id="deleteButton{{your.id}}">
Your modal
<div class="modal fade" id="confirmDeleteModal" tabindex="-1" caller-id="" role="dialog" aria-labelledby="confirmDeleteModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body confirm-delete">
This action is permanent!
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger" data-dismiss="modal" id="confirmDeleteButtonModal">Delete</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(document).on('click', '.confirm-delete', function () {
$("#confirmDeleteModal").attr("caller-id", $(this).attr("id"));
});
$(document).on('click', '#confirmDeleteButtonModal', function () {
var caller = $("#confirmDeleteButtonModal").closest(".modal").attr("caller-id");
window.location = $("#".concat(caller)).attr("href");
});
</script>
Solution 5:[5]
I got the example from @dipesh, but to works for me I needed to change somethings(tag 'a' and javascript) to get the correct element.
my script
function delete_user(selected_user){
document.getElementById("item-delete-form").action = selected_user.href
}
my link in the list for delete item will be:
<a
href="{% url 'item-delete' item.id %}"
class="dropdown-item text-danger"
data-toggle="modal"
data-target="#delete-item-modal"
onclick="delete_user(this)""
>
Remove
</a>
my modal
<div class="modal fade" id="delete-item-modal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p>Are you sure, You want to remove this item?</p>
</div>
<div class="justify-content-between mb-2 mr-2 text-right">
<form method="post"
id="item-delete-form"
>
<button type="button" class="btn btn-secondary mr-1" data-dismiss="modal">Cancel</button>
{% csrf_token %}
<button type="submit" class="btn btn-danger" id="confirm-delete-item-button">Delete</button>
</form>
</div>
</div>
</div>
</div>
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 | dipesh |
| Solution 2 | spst |
| Solution 3 | Alexis Le Dain |
| Solution 4 | Gorkhali Khadka |
| Solution 5 | Igor Matheus |
