How to prevent the Laravel 10 Jetstream modal from closing on an outside click? The user should close the modal window only by clicking on the button. Here is how!

To prevent Jetstream modal from closing we need to first understand why is it closing in first place.  So let's take a look how does it work, let's open modal.blade.php from views/components , and here we can see this line:

                    <div x-show="show" class="fixed inset-0 transition-all transform" x-on:click="show = true" 
...
                  

so the line:
x-on:click="show"
will actually close the modal window on backdrop click

The easiest way will be to just remove it, but we can also pass param to the modal.blade and based on that we can decide should we close the modal on backdrop click.

To pass param to modal.blade.php we have to extend the where we are including it on our blade templates. Let's say we are having custom modal:

                      <x-ialog-modal wire:model="showingModalCookieConsent" preventBackdropClose='true' class="text-slate-500">

        <x-slot name="title">
            <h3>{{__('frontend.Modal title')}}</h3>
        </x-slot>

        <x-slot name="content">
....
                  

as you can see we are passing preventBackdropClose='true' to dialog modal

and then we can update modal.blade,php to something like this:

                    @props(['id', 'maxWidth','preventBackdropClose'])

@php
$id = $id ?? md5($attributes->wire('model'));

$maxWidth = [
    'sm' => 'sm:max-w-sm',
    'md' => 'sm:max-w-md',
    'lg' => 'sm:max-w-lg',
    'xl' => 'sm:max-w-xl',
    '2xl' => 'sm:max-w-2xl',
][$maxWidth ?? '2xl'];
@endphp

<div
    
    x-data="{ show: @entangle($attributes->wire('model')),preventBackdropClose:{{$preventBackdropClose}}, }"
    x-on:close.stop="show = false"
    x-on:keydown.escape.window="show = false"
    x-show="show"
    id="{{ $id }}"
    class="fixed inset-0 z-50 px-4 py-6 overflow-y-auto jetstream-modal sm:px-0"
    style="display: none;"
>
    <div x-show="show" class="fixed inset-0 transition-all transform" 
            x-on:click="show = preventBackdropClose" 
            x-transition:enter="ease-out duration-300"
            x-transition:enter-start="opacity-0"
            x-transition:enter-end="opacity-100"
            x-transition:leave="ease-in duration-200"
            x-transition:leave-start="opacity-100"
            x-transition:leave-end="opacity-0">
        <div class="absolute inset-0 bg-gray-500 opacity-75 dark:bg-gray-900"></div>
    </div>

    <div x-show="show" class="mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
                    x-trap.inert.noscroll="show"
                    x-transition:enter="ease-out duration-300"
                    x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
                    x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
                    x-transition:leave="ease-in duration-200"
                    x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
                    x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
        {{ $slot }}
    </div>
</div>

                  

two important lines in order to prevent backdrop click are:

                    // to get the preventBackdropClose param
@props(['id', 'maxWidth','preventBackdropClose'])
...

// use it to prevent/enable backdrop click close
x-on:click="show = preventBackdropClose"