Skip to content

👾 Livewire Help Guide

Valeria Stamenova edited this page Apr 26, 2024 · 2 revisions

Introduction

During the development of the second edition of the IT Conference, we discovered Livewire. What's Livewire? The easiest way to explain Livewire is:

Livewire is a full-stack framework for Laravel that makes building dynamic interfaces simple, without leaving the comfort of Laravel.

Livewire has a rather steep learning curve, but it doesn't need to be like that. Livewire's documentation is written quite well but it can be a lot when you're opening it for the first time. In this page over here, you can discover the most used cases of Livewire components in our application.

During last year we used Livewire 2. The upgrade to Livewire 3 brought a lot of changes and some of the functions that worked previously now may have issues. Please if you find such and cannot handle it yourself, open it as an issue (bug) and tag @v-stamenova in it.

Modals

What are modals?

A modal (also called a modal window or lightbox) is a web page element that displays in front of and deactivates all other page content. To return to the main content, the user must engage with the modal by completing an action or by closing it. Modals are often used to direct users’ attention to an important action or piece of information on a website or application.

In our application we most often use modals in two places: we want a more dynamic user interface or we want the user to validate an action.

The first case can be found mostly within the company dashboard and the content moderator dashboard.

The latter can be found every time some "dangerous" action is occurring - like deleting an entity.

When should you use modals, it's up to you, but keep in mind Livewire is occasionally rather funky to work with because not all of the time the errors are actually useful. Until now we didn't have a uniform way of using modals - more or less it was "whatever worked". Now using the wire-elements' modal package it would be easier to make a systematic approach to it. In the following lines I'll show you the "algorithm" behind creating a rather simple confirm deletion modal.

Delete Modal

First thing that would be needed is to create your component. In this example case I'll be working with the Presentation model, therefore when generating my component I'll name it DeletePresentationModal and it'll be under the Livewire\Presentation.

NOTE: I'll be using php, but feel free to use sail if you don't have php on your Ubuntu distro.

php artisan make:livewire Presentation.DeletePresentationModal

This would generate two files - one would be Livewire\Presentation\DeletePresentationModal.php which would be your 'backend' of the component - all the logic goes there - the other one respectively will be in livewire\presentation\delete-presentation-modal.php since that will be your view part of the component.

Second thing you'll need to do is update your backend file - DeletePresentationModal. If you check the class name you'll see something like this:

class DeletePresentationModal extends Component

That must change, instead of extend Component, now it must be extends ModalComponent and add a new using use LivewireUI\Modal\ModalComponent;. Your component now should look something like:

<?php

namespace App\Livewire\Presentation;

use Illuminate\View\View;
use LivewireUI\Modal\ModalComponent;

class DeletePresentationModal extends ModalComponent
{

    /**
     * Renders the component
     * @return View
     */
    public function render() : View
    {
        return view('livewire.presentation.delete-presentation-modal');
    }
}

Since it is a delete component, we need to actually delete something. We need to specify in the backend that we'll have an entity. That happens by declaring a field - public Presentation $presentation. With that now your backend should be like this:

<?php

namespace App\Livewire\Presentation;

use App\Models\Presentation;
use Illuminate\View\View;
use Livewire\Component;
use LivewireUI\Modal\ModalComponent;

class DeletePresentationModal extends ModalComponent
{
    public Presentation $presentation;

    /**
     * Renders the component
     * @return View
     */
    public function render() : View
    {
        return view('livewire.presentation.delete-presentation-modal');
    }
}

Moving to the front end. In a sudden surge of altruism I created this basic view component called livewire-modal which can be used as a skeleton to your component. With this component acting like a wrapper, we can write a simple script like this:

<x-livewire-modal>
    <x-slot name="title">
        Delete presentation
    </x-slot>

    <x-slot name="content">
        <h3 class="font-bold text-red-600">{{ __('WARNING: this action cannot be undone') }}</h3>
        {{ __('Are you sure you want to delete this presentation?') }}
    </x-slot>

    <x-slot name="buttons">
        <x-secondary-button wire:click="$dispatch('closeModal')">
            {{ __('Cancel') }}
        </x-secondary-button>

        <form method="POST"
              action="{{ route('moderator.presentations.destroy', $presentation) }}">
            @csrf
            @method('DELETE')
            <x-danger-button class="ml-3" type="submit">
                {{ __('Delete Presentation') }}
            </x-danger-button>
        </form>
    </x-slot>
</x-livewire-modal>

NOTE: THIS DOES NOT UTILISE LIVEWIRE'S FULL POTENTIAL, THIS COMPONENT CAN EASILY DEAL WITH DELETING THE PRESENTATION ITSELF, BUT FOR SIMPLICITY SAKE IT JUST REDIRECTS TO A CONTROLLER WHO DOES THAT.

As you see the script is pretty easy to understand, probably a little more complicated is the following button:

        <x-secondary-button wire:click="$dispatch('closeModal')">
            {{ __('Cancel') }}
        </x-secondary-button>

You may feel intimidated by the wire:click="$dispatch('closeModal')" but it means simply put dispatch an event to your browser to close the modal.

One final thing is how to call the component. There are different ways, depending on the type of the component that is called and from where it is called - is the parent component a simple blade file or a livewire component? Refer to the snippet below that's taken from the wire-element's documentation.

<!-- Outside of any Livewire component -->
<button onclick="Livewire.dispatch('openModal', { component: 'edit-user' })">Edit User</button>

<!-- Inside existing Livewire component -->
<button wire:click="$dispatch('openModal', { component: 'edit-user' })">Edit User</button>

<!-- Taking namespace into account for component Admin/Actions/EditUser -->
<button wire:click="$dispatch('openModal', { component: 'admin.actions.edit-user' })">Edit User</button>

In our case we're outside of any livewire component and we have an attribute (the presentation) so our button that opens the modal will be quite long but still quite easy to understand:

<x-danger-button
     onclick="Livewire.dispatch('openModal', { component: 'presentation.delete-presentation-modal', arguments: {presentation: {{$presentation}}} })">
     {{ __('Delete Presentation') }}
</x-danger-button>

What's happening is that on click, a Livewire event is dispatched to open a modal, the component points to the view file of our component and the arguments show that the component requires a presentation and we pass the parameter which is well dynamic in this case.

You might want to resize the component, this can be doing by overriding the function modalMaxWidth in the back-end of the component.

/**
 * Supported: 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', '5xl', '6xl', '7xl'
 */
public static function modalMaxWidth(): string
{
    return 'xl';
}

Most of the hardwork in this scenario is carried by wire-element's modal package. If you have any issues or need help, reach out to @v-stamenova.