Delete Confirmation Dialog Box

What seems to be the problem: I have a datable I built following Caleb’s excellent guest episode on Laracasts.com and it works perfectly. I have an icon in the table to click to delete a record. I need to pop up a confirmation dialog box of “Are you sure you want to delete this user?” where cancel stops everything and OK triggers the delete and refresh.

Can someone point me in the right direction how to achieve this?

I have now been using Livewire 3 days and absolutely loving it!!!

Did you ever figure this out? I have a solution I came up with that mocks a callback for this exact issue. If not, it will probably be a little lengthy and my setup might be a little overkill, but you could take the concept of it to create your own.

Well, here’s the semi-quick version:

I originally built an alert display that works by listening for a sendalert event, and then expanded on it to send a callback event.

Here’s the component:

class Confirmationdisplay extends Component
{

    public $confirmations = [];

    public $listeners = [
        'sendConfirmation' => 'receiveConfirmation'
    ];

    public function receiveConfirmation($message, $callback, $callbackData = null)
    {
        $confirmation = [
            'message' => $message,
            'callback' => $callback,
            'callbackData' => $callbackData
        ];

        array_push($this->confirmations, $confirmation);
    }

    public function confirm($key)
    {
        $this->emit($this->confirmations[$key]['callback'], $this->confirmations[$key]['callbackData']);
        $this->removeConfirmation($key);
    }

    public function removeConfirmation($key)
    {
        unset($this->confirmations[$key]);
    }

    public function render()
    {
        return view('livewire.confirmationdisplay');
    }

}

For the view, design it how you want, the main points are:

You will need the key from the confimations array in your view:
@foreach($this->confirmations as $key => $confirmation)

Put the key into your binding for the confirm/accept:
<a href wire:click.prevent="confirm({{$key}})">Confirm</a>

And for the cancel/close:
wire:click="removeConfirmation({{$key}})"

From your “requesting” component, you only need a listener and two methods:

    public $listeners = [
        'deleteArtistCallback' => 'delete'
    ];

    public function confirmDelete($id)
    {
        $artistName = SingleReturn::artistName($id);
        $this->emit('sendConfirmation', "Delete Artist: $artistName?", 'deleteArtistCallback', $id);
    }

    public function delete($id)
    {
        $artist = Artist::find($id);
        $artist->delete();
    }

The confimDelete fires an event for the confirmation component to render with the parameters $message, $callback, $callbackData.

$callback is the event that is fired when confirm/accept is clicked, and what you are listening for in the requesting component. $callbackData is optional, and is whatever you need in your function; in most cases just the id.

If anyone is going to copy/paste this, just keep event name clashing and validation in mind. I stick my validation in my model with something along the lines of:

    public function delete($user = null)
    {
        $user = $this->getUserForModel($user);
        if ($user->is_admin) {
            return parent::delete();
        }
        return false;
    }

You could build the same concept with out the events into the original component, and css the alert where you want it. I made it separate because I use it in multiple areas of a project, so it’s very reusable.

Using these questions as katas, I tried an approach where the delete button is replaced by a confirmation button;
Component;

class Grid extends Component
{
    public $confirming;

    public function render()
    {
        return view('livewire.grid')->withCountries(Country::take(25)->get());
    }


    public function confirmDelete($id)
    {
        $this->confirming = $id;
    }

    public function kill($id)
    {
        Country::destroy($id);
    }
}

Blade;

<div>
    <table>
    @foreach($countries as $country)
        <tr>
            <td class="px-4 py-2" >{{ $country->id }}</td>
            <td class="px-4 py-2" >{{ $country->name }}</td>
            <td class="px-4 py-2" >{{ $country->fullname }}</td>
            <td class="px-4 py-2" >{{ $country->capital }}</td>
            <td>@if($confirming===$country->id)
                    <button wire:click="kill({{ $country->id }})"
                        class="bg-red-800 text-white w-32 px-4 py-1 hover:bg-red-600 rounded border">Sure?</button>
                @else
                    <button wire:click="confirmDelete({{ $country->id }})"
                        class="bg-gray-600 text-white w-32 px-4 py-1 hover:bg-red-600 rounded border">Delete</button>
                @endif
            </td>
        </tr>
    @endforeach
    </table>
</div>

So, the button is switched out if the current record matches the confirming property.

A confident user can double click the button and immediately delete. The buttons can be styled to reinforce that an additional action is required.
confirmations

11 Likes

@Snapey really nice idea and liked it, little improvement show group of two buttons yes and no (green and red color) yes to delete, no for don’t want to delete.

this feels so much better than a modal. it even feels more “current” to me. and I also liked @umefarooq addition to have a checkmark/cancel button. im using it on pages without IDs being passed so its just “delete the current model” basically. really dig this pattern.

Check i have created delete button better than modal, modal was creating problem after closing.

delete_btn

I think the other solutions brings awesome UI to Livewire.

Here is another option if you want to use the native confirm dialog from Javascript:

<button type="button" class="btn btn-danger btn-sm" x-on:click="return confirm('Are you sure?') ? @this.deleteEntity({{$entity->id}}) : false">Delete</button>

Using the x-on:click instead of wire:click and then use @this directive to access the Livewire method.

1 Like