Blog

guida livewire laravel

Guida laravel livewire:realizza un crud

Tempo di lettura: 19 minuti

Lo scopo di questa guida laravel livewire è quella di farvi conoscere un framework full-stack il quale semplifica la realizzazione di interfacce dinamiche e moderne senza richiedere l’utilizzo di javascript.

Ad esempio puoi utilizzare Livewire per implementare le seguenti funzionalità senza dover ricaricare la pagina:

  • impaginazione
  • convalida dei moduli
  • notifiche
  • anteprime dei caricamenti di file

Guida laravel livewire: prerequisiti

Per poter seguire il tutorial do per scontato che tu conosca laravel e che nella tua macchina vi siano installati:

Guida laravel livewire: imposta il progetto

Vai in una directory a tuo piacere, april il terminale e digita prima :

composer require laravel installer

questo ti consente diintsallare le dipendenze di composer nel tuo pc, quindi sempre da terminale digita:

laravel new larawire

dove larawire sarà il nome della cartella principale del progetto quindi il nome dello stesso.

Crea il database

Avvia xampp (o il tuo server predefinito) e crea il database per l’applicazione, apri la schell e digita:

guida laravel livewire

quando ti chiede la password dai semplicemente invio.

quindi digita:

Create DATABASE laraware_db;

poi per aver conferma digita:

guida laravel livewire

quindi , se tutto a posto, digita exit per 2 volte. Perfetto hai creato il database 🙂 🙂

Intsalla le dipendenze per il backend

Viso che l’unica dipendenza relativa al backend è Livewire, installalo, da terminale, mediante il comando:

composer require livewire/livewire

nel caso in cui volessi installare una versione specifica dovresti digitare:

composer require livewire/livewire:2.3

dove :2.3 sta appunto per la versione.

Configura il database

Aprite la migrazione predefinita relativa ad Users e modificate come di seguito:

database/migrations/2014_10_12_000000_create_users_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->enum('user_type',['admin','user'])->default('user');//aggiungi questo
            $table->tinyInteger('age');// aggiungi questo
            $table->string('address');// aggiuni questo
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

successivamente avremo bisogno di popolare tale tabella , noi lo faremo con dei dati finti grazie alla factories, per cui aprite database/factories/UserFactory.php e digitate:

...
    public function definition()
    {
        return [
            'name' => $this->faker->name(),
            'email' => $this->faker->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
            //agiungi questi
            'user_type'=>'user',
            'age'=>$this->faker->numberBetween(18,60),
            'address'=>$this->faker->address
        ];
    }
...

se volete saperne di più sui Faker in laravel andate su https://github.com/fzaninotto/Faker.

Ora aprite database/seeders/DatabaseSeeder.php e decommentate la chiamata relativa al realizzare gli utenti fittizzi:

...

    public function run()
    {
         \App\Models\User::factory(10)->create();
    }

..

non dimenticarti di configurare l’indirizzo del db nel file .env:

...
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laraware_db
DB_USERNAME=root
DB_PASSWORD=
...

quindi esegui la migrazione ed il seeder:

php artisan migrate
php artisan db:seed

Guida laravel livewire: configura le dipendenze lato front-end

Utilizzeremo lo scaffold laravel per Bootstrap, quindi come prima cosa installate il pacchetto laravel/ui:

composer require laravel/ui

Ora installa Bootstrap :

npm install bootstrap@next @popperjs/core --save-dev

quindi , una volta terminata l’installazione digita:

npm install && npm run dev

ora aggiungi Font Awesome al file resources/sass/app.scss:

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Variables
@import 'variables';


// Bootstrap
@import '~bootstrap/scss/bootstrap';

// add these:
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
@import "~@fortawesome/fontawesome-free/scss/brands";
@import "~@fortawesome/fontawesome-free/scss/regular";
@import "~@fortawesome/fontawesome-free/scss/solid";

quindi sei pronto per installare le dipendenze:

npm install @fortawesome/fontawesome-free && npm install

Crea il componente Livewire

Per realizzare un componente Livewire puoi utilizzare il comando make:livewire, quindi da terminale digita:

php artisan make:livewire LiveTable

il quale creerà i seguenti file:

  • app/Http/Livewire/LiveTable.php – controller per il componente
  • resources/views/livewire/live-table.blade.php – la view del componente

ora apri resources/views/livewire/live-table.blade.php ed aggiungi quanto segue:

<div>
    <div class="row mb-4">
        <div class="col-md-12">
            <div class="float-right mt-5">
                <input wire:model="search" class="form-control" type="text" placeholder="Search Users...">
            </div>
        </div>
    </div>

    <div class="row">
        @if ($users->count())
            <table class="table">
                <thead>
                <tr>
                    <th>
                        <a wire:click.prevent="sortBy('name')" role="button" href="#">
                            Name
                            @include('includes.sort-icon', ['field' => 'name'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('email')" role="button" href="#">
                            Email
                            @include('includes.sort-icon', ['field' => 'email'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('address')" role="button" href="#">
                            Address
                            @include('includes.sort-icon', ['field' => 'address'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('age')" role="button" href="#">
                            Age
                            @include('includes.sort-icon', ['field' => 'age'])
                        </a>
                    </th>
                    <th>
                        <a wire:click.prevent="sortBy('created_at')" role="button" href="#">
                            Created at
                            @include('includes.sort-icon', ['field' => 'created_at'])
                        </a>
                    </th>
                    <th>
                        Delete
                    </th>
                    <th>
                        Edit
                    </th>
                </tr>
                </thead>
                <tbody>
                @foreach ($users as $user)
                    <tr>
                        <td>{{ $user->name }}</td>
                        <td>{{ $user->email }}</td>
                        <td>{{ $user->address }}</td>
                        <td>{{ $user->age }}</td>
                        <td>{{ $user->created_at->format('m-d-Y') }}</td>
                        <td>
                            <button class="btn btn-sm btn-danger">
                                Delete
                            </button>
                        </td>
                        <td>
                            <button class="btn btn-sm btn-dark">
                                Edit
                            </button>
                        </td>
                    </tr>
                @endforeach
                </tbody>
            </table>
        @else
            <div class="alert alert-warning">
                Your query returned zero results.
            </div>
        @endif
    </div>

    <div class="row">
        <div class="col">
            {{ $users->links() }}
        </div>
    </div>
</div>

come potete notare è un sacco di codice, ma niente paura lo vedremo un pò alla volta.

Partiamo dall’inzio:

...
            <div class="float-right mt-5">
                <input wire:model="search" class="form-control" type="text" placeholder="Search Users...">
            </div>
...

in questa parte implementiamo un campo di ricerca per gli utenti da trovare. Vogliamo che gli stessi possano vedere i risultati delle loro query durante la digitazione.

Il modo in cui si implementa è grazie a wire:model il quale ci consente di passare il nome della variabile nella classe  del componente Http/Livewire/LiveTable.php.

Qualunque cosa l’utente digiti in quel campo verrà sincronizzato con il valore di quella variabile. Nel nostro caso vincoliamo la variabile search.

Più avanti nel codice per la classe del componente Http/Livewire/LiveTable.php, vedrai la variabile associata come nel codice seguente. Queste sono chiamate proprietà in Livewire:

// app/Http/Livewire/LiveTable.php
<?php
class LiveTable extends Component
{
  public $search = ''; // don't add this yet
}

Successivamente, abbiamo le intestazioni della tabella. Qui stiamo usando wire:click.preventper ascoltare gli eventi di clic nell’elemento link. Queste sono chiamate azioni in Livewire.

In sostanza, ti consentono di ascoltare gli eventi del browser ma di rispondere utilizzando metodi nel back-end. L’uso .preventimpedisce l’azione predefinita del browser.

Il valore fornito a questo è il nome del metodo che si desidera eseguire nella classe del componente. In questo caso lo è sortBy. Quindi passiamo il nome della colonna che vogliamo ordinare:

...
                    <th>
                        <a wire:click.prevent="sortBy('name')" role="button" href="#">
                            Name
                            @include('includes.sort-icon', ['field' => 'name'])
                        </a>
                    </th>
...

Ed ecco come appare il metodo corrispondente nella classe del componente Http/Livewire/LiveTable.php:

// app/Http/Livewire/LiveTable.php
public function sortBy($field)
{
  //
}

inoltre come si può notare nel codice sopra ho incluso un altro file di view chiamato sort-icon sotto la directory includes. Quindi realiziamolo subito resources/views/includes/sort-icon.blade.php arpitelo ed aggiungete quanto segue:

@if ($sortField !== $field)
    <i class="text-muted fas fa-sort"></i>
@elseif ($sortAsc)
    <i class="fas fa-sort-up"></i>
@else
    <i class="fas fa-sort-down"></i>
@endif

questo codice renderà l’icona di ordinamento corrente in base all’ordinamento selezionato dall’utente.

Questo praticamente è tutto per quel che riguarda il markup. Il resto dello stesso è il solito del modello blade, dove con @if mostreremo qualche cosa in modo condizionale e con links() mostriamo l’impaginazione.

Modifica la classe LiveTable

Apri Http/Livewire/LiveTable.php ed aggiungi:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Livewire\WithPagination;
use App\Models\User;

class LiveTable extends Component
{
    use WithPagination;

    public $sortField = 'name'; // default sorting field
    public $sortAsc = true; // default sort direction
    public $search = '';

    public function sortBy($field)
    {
        if ($this->sortField === $field) {
            $this->sortAsc = !$this->sortAsc;
        } else {
            $this->sortAsc = true;
        }

        $this->sortField = $field;
    }

    public function render()
    {
        return view('livewire.live-table', [
            'users' => User::search($this->search)
                ->orderBy($this->sortField, $this->sortAsc ? 'asc' : 'desc')
                ->simplePaginate(10),
        ]);
    }
}

Come accennato in precedenza, ho associato il valore della variabile  search a un campo di testo specifico nel lato client tramite wire:model.

Quindi ogni volta che l’utente digita qualcosa, anche la variabile search viene aggiornata. Di conseguenza anche il componente viene nuovamente reinderizzato.

Questo perché nel metodo render()dipendiamo dal valore della variabile searchper recuperare i dati dell’utente.

Quindi, per ogni sequenza di tasti, stiamo effettivamente recuperando i dati dal database fornendo la query dell’utente e l’ordinamento selezionato (daremo un’occhiata a come migliorarlo più avanti nella sezione Ottimizzazioni ):

...
    public function render()
    {
        return view('livewire.live-table', [
            'users' => User::search($this->search)
                ->orderBy($this->sortField, $this->sortAsc ? 'asc' : 'desc')
                ->simplePaginate(10),
        ]);
    }
...

Il metodo sortBy()è ciò che utilizziamo per aggiornare il campo per l’ordinamento della tabella degli utenti. Ogni campo può essere ordinato in ordine crescente o decrescente.

Per impostazione predefinita, fare clic su un campo di ordinamento lo ordinerà in ordine crescente. Facendo nuovamente clic su di esso si farà semplicemente l’opposto:

...
    public function sortBy($field)
    {
        if ($this->sortField === $field) {
            $this->sortAsc = !$this->sortAsc;
        } else {
            $this->sortAsc = true;
        }

        $this->sortField = $field;
    }
...

Aggiorna il modello User

Quando filtriamo la tabella  users, usiamo il metodo search(). Ma non l’abbiamo ancora aggiunto.

Aggiorna app/Models/User.php includendo il metodo search(). Questo filtra la tabella utente per restituire solo utenti di tipo user. Quindi il resto delle condizioni saranno i campi che vogliamo utilizzare per filtrare il campo di ricerca:

...
    public static function search($query)
    {
        return empty($query) ? static::query()->where('user_type', 'user')
            : static::where('user_type', 'user')
                ->where(function ($q) use ($query) {
                    $q
                        ->where('name', 'LIKE', '%' . $query . '%')
                        ->orWhere('email', 'LIKE', '%' . $query . '%')
                        ->orWhere('address', 'LIKE ', '%' . $query . '%');
                });
    }
...

Utilizzo del componente LiveWire

Ora apri il file di rotta routes/web.php e modifica come di seguito:

Route::get('/', function () {
    return view('index');
});

quindi crea la view resources/views/index.blade.php e aggiungi:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ config('app.name') }}</title>
    <link rel="stylesheet" type="text/css" href="{{ asset('css/app.css') }}">
</head>
<body>

    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-9">
                <livewire:live-table />
            </div>
        </div>
    </div>

    @livewireScripts
    <script src="{{ asset('js/app.js') }}"></script>

</body>
</html>

In pratica qui stiamo utilizzando il componente LiveTable creato in precedenza.

Possiamo renderlo nella pagina come faresti con un componente standard. L’unica differenza è che dobbiamo anteporre al nome del componente livewire:e dobbiamo anche usarlo @livewireScriptsper eseguire il rendering del file JavaScript di Livewire.

Ora provate ad eseguire l’app mediante Artisan:

php artisan serve

quindi accedi all’indirizzo http://127.0.0.1:8000/:

guida laravel con livewire

Elimina Utenti

Come in precedenza, utiliziamowire:clickper ascoltare gli eventi di clic sul pulsante Elimina. Solo che questa volta non chiameremo direttamente un metodo nella classe del componente.

Questo perché si tratta di un’operazione di cancellazione. Non vogliamo che gli utenti cancellino qualcuno per errore, quindi dobbiamo mostrare una sorta di conferma prima di procedere con l’eliminazione.

Questo è il caso d’uso perfetto per gli eventi Livewire  il quale consente di inviare e ricevere eventi specifici dal server e viceversa.

Possiamo utilizzarlo chiamando il metodo $emit(). Il suo primo argomento sarà il nome dell’evento, mentre quelli che seguono sono gli argomenti che vuoi passare all’ascoltatore per quell’evento. In questo caso, abbiamo il file evento deleteTriggered e stiamo passando l’ID e il nome dell’utente come argomenti all’ascoltatore.

ok quindi apri resources\views\livewire\live-table.blade.php e aggiorna come di seguito:

...
<button class="btn btn-sm btn-danger" wire:click="$emit('deleteTriggered',{{$user->id}},'{{$user->name}}')">
   Delete
</button>
...

Possiamo quindi ascoltare quell’evento sul server o sul lato client. Poiché tutto ciò che vogliamo è mostrare una conferma quando questo evento viene attivato, lo ascoltiamo sul lato client.

Crea il file  resources/js/users.js e aggiungi quanto segue. Come puoi vedere, abbiamo accesso a id namedell’utente tramite gli argomenti passati all’ascoltatore:

Livewire.on("deleteTriggered", (id, name) => {
    const proceed = confirm(`Are you sure you want to delete ${name}`);

    if (proceed) {
        Livewire.emit("delete", id);
    }
});

Una volta che l’utente è d’accordo, emettiamo l’evento che effettivamente lo cancellerà . Per ascoltare gli eventi nel back-end, create un $listenersossia un array che contenga il nome degli ascoltatori e i metodi di classe a cui sono mappati.

In questo caso, il nome dell’evento e il metodo sono gli stessi, quindi aggiungiamo semplicemente delete.Il metodo delete()eliminerà quindi l’utente con il corrispondente id:

// app/Http/Livewire/LiveTable.php
protected $listeners = ['delete'];

public function sortBy($field)
{
    //
}

public function delete($id)
{
    User::find($id)
        ->delete();
}

se desiderate una notifica dopo aver rimosso un utente , potete inviare un evento del browser in questo modo:

Http/Livewire/LiveTable.php

public function delete($id)
{
    $user = User::findOrFail($id);
    User::find($id)
        ->delete();
    $this->dispatchBrowserEvent('user-deleted',['user_name'=>$user->name]);
}

Quindi, sul lato client, ascolta questo evento tramite l’ API del listener di eventi del browser standard . Qui, stiamo semplicemente mostrando un avviso che contiene il nome dell’utente eliminato:

resources/js/users.js

Livewire.on("deleteTriggered", (id, name) => {
    const proceed = confirm(`Are you sure you want to delete ${name}`);

    if (proceed) {
        Livewire.emit("delete", id);
    }
    window.addEventListener("user-deleted",(event)=>{
        alert(`${event.detail.user_name} was deleted`)
    })
});

 

non dimenticare di aggiungere users.js su webpack.mix.js:

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/sass/app.scss', 'public/css')
    .postCss('resources/css/app.css', 'public/css')
    .js("resources/js/users.js","public/js)
    .sourceMaps();

quindi compila:

npx mix

oppure:

npm run dev

Apri il file resources/views/index.blade.php ed aggiungi il percorso relativo ad users.js:

...
<script src="{{ mix('js/app.js') }}"></script>
<script src="{{ mix('js/users.js') }}"></script>
...

ora vai su http://127.0.0.1:8000/ e prova ad eliminare un utente.

Guida laravel livewire: creare nuovi utenti

Una volta realizzato il metodo per la cancellazione di utenti arriva il momento di crearne di nuovi. Aprite il file resources/views/livewire/live-table.blade.php ed aggiungiamo un pulsante che ci consenta di aggiungere un utente:

<div>
    <div class="row mb-4">
        <div class="col-md-12">
            <div class="float-right mt-5">
                <button class="btn btn-success" wire:click="$emit('triggerCreate')">Create a new User</button>
            </div>
            <div class="float-right mt-5">
                <input wire:model="search" class="form-control" type="text" placeholder="Search Users...">
            </div>
        </div>
    </div>
....

come potete notare ancora una volta utilizzo wire:click per attivare l’evento triggerCreate.

aggiorna il file resources/js/users.js aggiungendo in fondo il seguente metodo:

Livewire.on("triggerCreate",() => {
    $("#user-modal").modal("show")
})

NOTA BENE: come si evince dal suddetto codice utilizzo jQuery per aprire una modal. Per i puristi del codice non bisognerebbe mai mescolare entrambe le librerie.

In questo caso è perdonabile in quanto si tratta di una semplice riga. Ciò vale anche per altre librerie o framework come Angular, Vue o React.

Realizza il componente Livewire UserForm

Realiziamo quindi il componente UserForm digitando da terminale:

php artisan make:livewire UserForm

come potete notare questi mi crea sia la classe che la vista.

guida laravel livewire

  • resources/views/livewire/user-form.blade.php
  • Http/Livewire/UserForm.php

apri il file resources/views/livewire/user-form.blade.php ed aggiungi quanto segue:

<div>
    <form wire:submit.prevent="save">
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" class="form-control" id="name" name="name" wire:model="name">
            @error('name') <span class="text-danger">{{ $message }}</span> @enderror
        </div>

        <div class="form-group">
            <label for="exampleInputPassword1">Email</label>
            <input type="email" class="form-control" id="email" name="email" wire:model="email">
            @error('email') <span class="text-danger">{{ $message }}</span> @enderror
        </div>

        <div class="form-group">
            <label for="age">Age</label>
            <input type="number" class="form-control" id="age" name="age" wire:model="age">
            @error('age') <span class="text-danger">{{ $message }}</span> @enderror
        </div>

        <div class="form-group">
            <label for="address">Address</label>
            <input type="text" class="form-control" id="address" name="address" wire:model="address">
            @error('address') <span class="text-danger">{{ $message }}</span> @enderror
        </div>

        <button class="btn btn-primary" type="submit">Save</button>
    </form>
</div>

questo codice risulta familiare a molti di voi in quanto ,in fin dei conti, si tratta di un semplice modello Blade. L’unica differenza sta nell’aver aggiunto alcuni attributi relativi a Livewire visti in precedenza.

Se esaminiamo il codice vediamo che <form wire:submit.prevent=”save”> verrà attivato una volta cliccato sul <button class=”btn btn-primary” type=”submit”>Save</button> ovvero il pulsante di salvataggio/invio del form.

In fine usiamo wire:model per associare ogni campo ad una proprietà specifica nella classe del componente ed , inoltre, con:

@error('name') <span class="text-danger">{{ $message }}</span> @enderror

riusciamo a gestire , mediante questo codice relativo al modello blade, errori nei campi del form. Gestibile anche da Livewire.

File resources/views/index.blade.php

Modifica il file resources/views/index.blade.php aggiungi quanto segue:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ config('app.name') }}</title>
    <link rel="stylesheet" type="text/css" href="{{ asset('css/app.css') }}">
</head>
<body>
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-9">
            <livewire:live-table />
        </div>
    </div>
</div>

<div class="modal" tabindex="-1" role="dialog" id="user-modal">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">User</h5>
                <button style="border: none !important; background: transparent !important" type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
                    <i style="color: red; font-size: 22px;border:none !important" class="fas fa-times-circle"></i>
                </button>
            </div>

            <div class="modal-body">
                <livewire:user-form/>
            </div>


        </div>
    </div>
</div>

@livewireScripts
<script src="{{ asset('js/app.js') }}"></script>
<script src="{{ asset('js/users.js') }}" defer></script>

</body>
</html>

 

Modifica il file Http/Livewire/UserForm.php

Una volta implementato il lato front-end non ci resta che modificare il back-end, per cui aprite la classe relativa ad essa ed aggiungete quanto segue:

Http/Livewire/UserForm.php

use App\Models\User; // add this

class UserForm extends Component
{

    // add these
    public $name;
    public $email;
    public $age;
    public $address;

    public function render()
    {
        return view('livewire.user-form');
    }

    // add this
    public function save()
    {
        $validated = $this->validate([
            'name' => 'required|min:10',
            'email' => 'required|email|min:10',
            'age' => 'required|integer',
            'address' => 'required|min:10',
        ]);

        User::create(array_merge($validated, [
            'user_type' => 'user',
            'password' => bcrypt($this->email)
        ]));

    
        $this->dispatchBrowserEvent('user-saved', ['action' => 'created', 'user_name' => $this->name]);
        $this->emitTo('live-table', 'triggerRefresh');
        $this->resetForm();
    }

    public function resetForm()
    {
        $this->user_id = null;
        $this->name = null;
        $this->email = null;
        $this->age = null;
        $this->address = null;
    }

}

Anche se si tratta di tanto codice non lo esamino tutto in quanto ci sono cose già spiegate e viste. Piuttosto esaminiamolo in alcuni particolari.

In primo luogo esaminiamone la convalida. Come potete notare non utilizzo una classe Request ma , bensì, ne utilizzo una standard relativa a Laravel. Questo perchè il Livewire tutto viene gestito attraverso chiamate AJAX quindi senza ricaricare la pagina cosa che farebbe la precedente e , quindi, nel nostro caso di sicuro ci restituirebbe un errore.

$validated = $this->validate([
    'name' => 'required|min:10',
    'email' => 'required|email|min:10',
    'age' => 'required|integer',
    'address' => 'required|min:10',
]);

Inoltre utiliziamo il metodo emitTo() invece di emit() il quale consente a diversi componenti di comunicare tra loro attraverso gli eventi. Come potete vedere questi accetta il nome del componente come primo argomento ed il nome dell’evento come secondo:

...
        $this->dispatchBrowserEvent('user-saved', ['action' => 'created', 'user_name' => $this->name]);
        $this->emitTo('live-table', 'triggerRefresh');
...

come vedete utilizzo due venti separati( il primo relativo al browser e l’altro a livewire) quando , a dire il vero, ne potrei utilizzare solo uno. Il problema sta nel dover aggiornare la tabella dati ogni qualvolta inserisco un utente.

Aggiorna il file resources/js/users.js

Benissimo aprite il file resources/js/users.js ed aggiornate come segue:

Livewire.on("deleteTriggered", (id, name) => {
    const proceed = confirm(`Are you sure you want to delete ${name}`);

    if (proceed) {
        Livewire.emit("delete", id);
    }
    window.addEventListener("user-deleted",(event)=>{
        alert(`${event.detail.user_name} was deleted`)
    })
});

Livewire.on("triggerCreate",() => {
    $("#user-modal").modal("show")
})

windows.addEventListener("user-saved",(event)=>{
    $("#user-modal").modal("hide");
    alert(`User ${event.detail.user_name} was ${event.detail.action} !`);
})

ora apri la classe LiveTable ed aggiungi l’ascoltatore per triggerRefresh. Questo punta ad un metodo $refresh , il quale non necessita di essere dichiarato come metodo di classe perchè trattasi di funzione integrata per tutte le classi di Livewire e ci consente ricaricare l’intero componente.

Http/Livewire/LiveTable.php

...
protected $listeners = ['delete', 'triggerRefresh'=>'$refresh'];
...

Aggiornare gli utenti

Per concludere la guida andiamo a realizzare il metodo per aggiornare gli utenti. Apri il file resources/views/livewire/live-table.blade.php ed aggiorna il pulsante di modifica come segue:

...
<button class="btn btn-sm btn-dark" wire:click="$emitTo('user-form','triggerEdit',{{$user}})">
    Edit
</button>
...

dato che ci troviamo nel componente LiveTable ed il metodo di modifica dovrebbe trovarsi nel componente UserForm devo usare il metodo $emitTo() per poter emettere triggerEdit in esso.

Ora vai sul file app/Http/Livewire/UserForm.php e modifica come di seguito in modo tale da poter ascoltare triggerEdit:

...
   public function triggerEdit($user)
    {
        $this->user_id = $user['id'];
        $this->name = $user['name'];
        $this->email = $user['email'];
        $this->age = $user['age'];
        $this->address = $user['address'];

        $this->emit('dataFetched',$user);
    }
...

Ascolta l’evento dataFetched lato client. Poichè abbiamo di già i campi popolati, possiamo semplicemente aprire la modale:

resources/js/users.js

...
Livewire.on("dataFetched", (user) => {
    $("#user-modal").modal("show");
});

infine aggiorna il metodo save() nella classe del componente UserForm in modo tale da poter gestire anche gli aggiornamenti. Lo faremo controllando il valore di user_id nei campi del form inserendo una condizione. In poche parole se questo è valorizzato faremo una cosa altrimenti un’altra:

app/Http/Livewire/UserForm.php

...
    // add this
    public function save()
    {
        $validated = $this->validate([
            'name' => 'required|min:10',
            'email' => 'required|email|min:10',
            'age' => 'required|integer',
            'address' => 'required|min:10',
        ]);

        if($this->user_id) {
            User::find($this->user_id)
                ->update([
                    'name'=>$this->name,
                    'email'=>$this->email,
                    'age'=>$this->age,
                    'address'=>$this->address,
                ]);
            $this->dispatchBrowserEvent('user-saved', ['action' => 'created', 'user_name' => $this->name]);
        } else {
            User::create(array_merge($validated, [
                'user_type' => 'user',
                'password' => bcrypt($this->email)
            ]));
        }
...

dimenticavo in cima aggiungi prima:

...
class UserForm extends Component
{

    // add these
    public $user_id;// aggiungi questo
    public $name;
    public $email;
    public $age;
    public $address;
...

Benissimo ora siamo in grado anche di modificare un utente 🙂 🙂

Conclusioni ed ottimizzazioni

Come avrai già notato, quando inserisci una stringa nel campo di ricerca questo attiva immediatamente una chiamata AJAX che estrae i dati aggiornati dal server.

Questo invia una query al database ogni volta e non va bene, immaginate di fare richieste ad un server esterno in modalità asincrona.

L’ideale sarebbe quello di ritardare tale richiesta.

Quindi apri il file resources/views/livewire/live-table.blade.php ed aggiungi come segue:

...
            <div class="float-right mt-5">
                <input wire:model.debounce.800ms="search" class="form-control" type="text" placeholder="Search Users...">
            </div>
...

in pratica ritardiamo la richiesta di 8 secondi potete modificare tale valore in base alle vostre esigenze, ora testatelo.

Ottimiziamo i campi del modulo

Anche in questo caso quando inviamo una richiesta al server questi avviene in maniera istantanea e ciò non è reale in un contesto dove lo stesso si trova in remoto. per cui rallentiamolo simulando una situazione reale.

Aprite resources/views/livewire/user-form.blade.php ed aggiungete:

...
<input type="text" class="form-control" id="name" name="name" wire:model.lazy="name">
...

in tutti i campi.

Ora provate 🙂 🙂

Conclusione

Questo è tutto! In questo tutorial, hai appreso le basi dell’utilizzo di Livewire per rendere le tue app Laravel più dinamiche senza scrivere una riga di codice JavaScript per recuperare e inviare dati al server.

Nello specifico, abbiamo creato una semplice applicazione CRUD che utilizza Livewire per eliminare la necessità di pacchetti front-end come Datatables per implementare la ricerca e l’ordinamento nelle tabelle.

Abbiamo anche rimosso la necessità di aggiornare la pagina nel momento in cui viene inviato il modulo. Infine, abbiamo utilizzato sia gli eventi di Livewire che gli eventi del browser per fare in modo che il front-end e il back-end comunichino tra loro senza la necessità di scrivere codice AJAX.

È possibile visualizzare il codice sorgente del progetto in questo repository GitHub .

Se volete Approfondire le conoscenze su Laravel potete seguire il  corso completo su Udemy sempre scontato a 9.99/12.99 € , inoltre, nel momento in cui non foste soddisfatti, avete la possibilità di ottenere il rimborso completo dello stesso entro 30 giorni dalla data di acquisto!

Se volete Approfondire le conoscenze su REACT E NODEJS CON EXPRESS E MONGODB potete seguire il  corso completo su Udemy sempre scontato a 9.99/12.99 € , inoltre, nel momento in cui non foste soddisfatti, avete la possibilità di ottenere il rimborso completo dello stesso entro 30 giorni dalla data di acquisto!

REACT NODEJS FULLSTACK

Share and Enjoy !

0Shares
0 0

Chi è ?

Lucio Ticali è un Web & App developer con la passione per il web marketing,si occupa anche di tecniche di indicizzazione del sito e di promozione dello stesso (SEO e SEM).

Lascia la tua opinione