Modals stop working when deleting components

What seems to be the problem:
I am running a foreach loop with modals. Users click on a trash icon, a modal pops up as a confirmation message and upon clicking delete, I send a wire:action to delete the component and mount the page again. the problem I have is after deleting two or three, some modals seem to stop opening and only when I refresh the page am I able to click on the trash icon again and have the modal open. I think it has something to do with modals being deleted with the components? I am looking to an alternative solution for a confirmation message before deleting something using Livewire?

Any assistance and code snippets would be greatly appreciated for html, css, bootstrap or javascript.
Steps to Reproduce:

Are you using the latest version of Livewire:
Yes
Do you have any screenshots or code examples:
My html


My Livewire Controller

And the script code for close modal? Let me know too how work your component, because you are binding some parameters in mount and rewriting it…I’m using a lot of modals this days in my project, maybe can give you a hand

Hi, I would greatly appreciate if you could assist me. See the code you asked to see below:

<script>
		window.addEventListener('close_modal', event => {
		    $('.delete-' + event.detail.component_id).modal('hide');
		})
	</script>

And how you make the call to open the modal? Using the Bootstrap attr?

That’s correct yes. But I’m open to using a different solution if it would make for a better experience and code?

I’m no longer using Bootstrap for open and close modals. For example, in table for each row with buttons to edit and delete I make this:

<button wire:click="selectItem({{ $property->id }}, 'update')" class="btn btn-light-secondary"
                                                        data-placement="top" title="Edit">                                               </button>
<button wire:click="selectItem({{ $property->id }}, 'delete')" class="btn btn-light-secondary"
                                                        data-placement="top" title="Delete">                                               </button>

In the component:

public function selectItem($itemId, $action)
    {
        if ($action == 'delete') {
            $this->dispatchBrowserEvent('openDeleteModal');
        }
        else {
            $this->emit('getUserModelId', $itemId);
            $this->dispatchBrowserEvent('openFormModal');
        }
    }

and in parent blade component or in scripts section:

        window.addEventListener('openFormModal', event => {
            $("#formModal").modal('show');
        })

        window.addEventListener('closeFormModal', event => {
            $("#formModal").modal('hide');
        })

        window.addEventListener('openDeleteModal', event => {
            $("#deleteModal").modal('show');
        })

        window.addEventListener('closeDeleteModal', event => {
            $("#deleteModal").modal('hide');
        })

The Delete modal is like this:

<!-- Delete Modal -->
                <div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="deleteModalLabel" aria-hidden="true" data-keyboard="false" data-backdrop="static">
                    <div class="modal-dialog">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title" id="deleteModalLabel">Delete User</h5>
                                <button type="button" class="close" wire:click="closeDeleteModal" aria-label="Close">
                                    <span aria-hidden="true">&times;</span>
                                </button>
                            </div>
                            <div class="modal-body">
                                <h3>Are you sure?</h3>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" wire:click="closeDeleteModal">Cancel</button>
                                <button type="button" class="btn btn-primary" wire:click="destroy">Yes</button>
                            </div>
                        </div>
                    </div>
                </div>

and in destroy method first run the deletion action and after call to close the modal. I’m not sure in your case, but is good clean every var that was involved in here, for example the selected item. Hope you understand and like this can help you. I will be around for any cuestion

This is a great solution, thank you very much, I have implemented it into my project and it works perfectly. Thank you so much! Already considering the edit side you included! Thanks @prospero

One question I have though is if you have any solutions for a “click away to close modal” function?

Its cool to know its working well for you too. Exploiting that all that you can!

Explain more…what precisely you want to do?

I would like for the user to be able to click outside the modal in the greyed out area to close the modal, as you would be able to with something like a bootstrap modal.

Ohh yeahh. I’m sorry but the code that I provide in the example have the attr for not close it out of the content of modal. Only delete the data-keyboard and data-backdrop from the parent div. In the cases of edit and delete, as well as you are selecting items or managing properties loading data, remember clear them always that modal is closed. In case for button you can manage calling a method that you declare for that, but when is closed by outside click use this script:

            $(document).ready(function(){
               $("#deleteModal").on('hidden.bs.modal', function(){
                   livewire.emit('forcedCloseModal');
            });

keep listening for this in the component and in the forcedCloseModal() method you can clear the vars

Thank you, you were right, by removing the data-keyboard and data-backdrop, the modals are now closing by simply clicking outside the modal. You have been a tremendous help, thank you again so much!

1 Like