[Django]-How to do Delete confirmation for a table data with bootstrap Modal in Django?

5👍

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.

👤dipesh

1👍

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>
👤spst

1👍

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">&times;</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,))

0👍

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>

0👍

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>

0👍

You can also do it without JavaScript (see also option 1 in the answer by @lemayzeur in this question). Give the modal a variable name and call it using item.id:

# in your link to the modal
data-target="#delete-item-modal-{{item.id}}"

# in your modal
id="delete-item-modal-{{item.id}}"

Leave a comment