Search code examples
laravelbootstrap-5laravel-livewire

How to dispatch modal window in livewire 3 after submit form?


i am struggling with showing modal window. After reservation is created and data are sent to database, immediately after that i need to show up modal window where user can insert verification code. But I cant figure out how to do that, official docs of livewire didnt helped me much. If is here anyone who has experience with that, i would be glad for any advice from this person. I updated code and now i am facing this problem

Uncaught TypeError: Cannot read properties of undefined (reading 'backdrop')
    at On._initializeBackDrop (modal.js:158:39)
    at new On (modal.js:69:27)
    at On.getOrCreateInstance (base-component.js:65:41)
    at HTMLButtonElement.<anonymous> (modal.js:363:22)
    at HTMLDocument.n (event-handler.js:118:19)

This is my booking component with functionality

<?php

namespace App\Livewire;

use Livewire\Component;
use App\Models\Reservation;
use App\Mail\ReservationMail;
use Illuminate\Support\Facades\Mail;
use App\Models\AvailableBusinessHour;
use App\Events\ShowVerificationModal; // Přidejte tuto řádku pro event

class Booking extends Component
{
    public $full_name;
    public $email;
    public $phone_number;
    public $reservation;

    public $selectedService;
    public $available_business_hour_id;
    public $selectedBusinessHourId;
    public $verification_code;
    public $successMessage;

    public $showVerificationModal = false;
    public $successMessageVisible;
    public $successMessageTimeout = 3000;

    public function render()
    {
        $this->available_business_hour_id = AvailableBusinessHour::whereDoesntHave('reservation')->orderBy('day')->orderBy('from')->get();
        return view('livewire.booking', [
            'emptyOption' => 'Vyber si čas rezervace',
        ]);
    }

    public function store()
{
    $this->validate([
        'full_name' => 'required|string|max:250',
        'email' => 'required|email|max:250',
        'phone_number' => 'required|phone:CZ',
        'selectedService' => 'required',
        'available_business_hour_id' => 'required|unique:reservations',
    ], [
        'available_business_hour_id.unique' => 'Tento termín byl již obsazen, vyber jiný pokud je nějaký dostupný.',
        'available_business_hour_id.required' => 'Výběr času objednání je povinné pole.',
        'phone_number.phone' => 'Chybný formát telefonního čísla.',
        'selectedService.required' => 'Toto je povinné pole',
    ]);

    $selectedBusinessHour = AvailableBusinessHour::find($this->selectedBusinessHourId);

    $verification_code = rand(100000, 999999);

    $reservation = Reservation::create([
        'full_name' => $this->full_name,
        'email' => $this->email,
        'phone_number' => $this->phone_number,
        'service' => $this->selectedService,
        'available_business_hour_id' => $this->selectedBusinessHourId,
        'day' => $selectedBusinessHour['day'],
        'from' => $selectedBusinessHour['from'],
        'to' => $selectedBusinessHour['to'],
        'verification_code' => $verification_code
    ]);

    $this->sendReservationConfirmationMail($reservation);

    $this->successMessage = 'Rezervace proběhla úspěšně.';
    $this->successMessageVisible = true;

    $this->showVerificationModal = true;

    $this->reset(['full_name', 'email', 'phone_number', 'available_business_hour_id']);
}

    public function sendReservationConfirmationMail($reservation)
    {
        Mail::to($reservation->email)->send(new ReservationMail($reservation));
    }

    public function services()
    {
        return ["Stříhání vlasů", "Stříhání + úprava vousů", "Barvení vousů", "Junior střih", "Úprava vousů"];
    }



this is its blade

<section id="booking">
    <div class="container">
        @if ($successMessageVisible)
            <div x-data="{ show: true }" x-init="setTimeout(() => show = false, {{ $successMessageTimeout }})" x-show="show" class="alert alert-success">
                {{ $successMessage }}
            </div>
        @endif
        <form wire:submit.prevent="store">
            @csrf
            <div class="col-12 mb-4">
                <h1 class="modal-title fs-5 text-center" id="bookingModalLabel">Objednej se</h1>
                <p class="">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Lorem, ipsum
                    dolor sit amet consectetur adipisicing elit.</p>
            </div>
            <div class="form-group col-12">
                <input type="text" wire:model="full_name" id="full_name" name="full_name" class="form-control"
                    placeholder="Celé jméno*" required>
            </div>
            <div class="form-group col-12">
                <input type="email" wire:model="email" id="email" name="email" class="form-control"
                    placeholder="Email*" required>
            </div>
            <div class="form-group col-12">
                <input type="text" wire:model="phone_number" id="phone_number" name="phone_number"
                    class="form-control" placeholder="Tel. číslo ve formátu +420700700700" required>
                @error('phone_number')
                    <span class="text-danger">{{ $message }}</span>
                @enderror
            </div>
            <div class="form-group col-12">
                <select wire:model="selectedService" class="form-control">
                    <option value="">Vyberte službu</option>
                    @foreach ($this->services() as $service)
                        <option value="{{ $service }}">{{ $service }}</option>
                    @endforeach
                </select>
                @error('selectedService')
                    <span class="text-danger">{{ $message }}</span>
                @enderror
            </div>

            <div class="form-group col-12 mt-3">
                <select wire:model="selectedBusinessHourId" class="form-control">
                    <option value="">{{ $emptyOption }}</option>
                    @foreach ($available_business_hour_id as $time)
                        <option value="{{ $time['id'] }}">{{ $time['formattedDayAndDate'] }} od {{ $time['from'] }} do
                            {{ $time['to'] }}</option>
                    @endforeach
                </select>
                @error('available_business_hour_id')
                    <span class="text-danger">{{ $message }}</span>
                @enderror
            </div>
            <div class="form-group col-12 text-center">
                <div class="cta-btns">
                    <button type="submit" class="btn btn-service me-sm-2"  data-bs-toggle="modal"
                        data-bs-target="#exampleModal">Odeslat</button>
                        @if ($showVerificationModal)

                            <livewire:verification-modal />
                        @endif
                </div>
            </div>
        </form>

    </div>
</section>



this is verification component

<?php

namespace App\Livewire;

use Livewire\Component;

class VerificationModal extends Component
{
    protected $listeners = ['showVerificationModal'];

    public function render()
    {
        return view('livewire.verification-modal');
    }


}

and its modal blade

<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
            <div class="verification-code-container">
                {{-- <input type="text" wire:model="verification_code" id="verification_code" name="verification_code" class="form-control" placeholder="Verifikační kód" required> --}}
            </div>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          <button type="button" class="btn btn-primary">Save changes</button>
        </div>
      </div>
    </div>
  </div>


I'm expecting that this thread will see somebody who has experience with that.


Solution

  • Surely you can achieve this by using Livewire Events. Once your data has been inserted into the database, you can dispatch the event from that method as:

    public function store()
    {
      ...
      ...
    
      $this->dispatch('show-verification-modal'); 
    }
    

    then in your balde component file, add the script to listen to that event and open the modal as:

    @script
     <script>
        $wire.on('show-verification-modal', () => {
          
          $('#exampleModal').modal('show');
           
        });
     </script>
    @endscript
    

    reference: https://livewire.laravel.com/docs/events