13

Livewire how to $emit event on <select> change (wire:model)

I need to fire event (fetch some data from DB in another component) on simple <select> change.

<select id="hall" wire:model="hall_id">...</select>

How to watch changes for this model? On VueJS we just set $watch or $computed properties, I believe in livewire should be something similar. It's strange why there is no wire:change directive.

This is how I'm trying to emit event now:

<?php

namespace App\Http\Livewire;

use App\Models\Event;
use App\Models\Hall;
use Livewire\Component;

class ShowReservationForm extends Component
{
    public $hall_id = '';

    protected $queryString = [
        'hall_id' => ['except' => ''],
    ];

    public function mounted()
    {
        //
    }

    public function updatedHallId($name, $value)
    {
        $this->emit('hallChanged', $value);
    }

    public function render()
    {
        return view('livewire.show-reservation-form', [
            'halls' => Hall::all(),
        ]);
    }

    public function getHallEventsProperty()
    {
        return Event::where('hall_id', $this->hall_id)->get();
    }
}

and catch it:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class ShowReservations extends Component
{
    protected $listeners = ['hallChanged'];

    public $showTable = false;

    public function render()
    {
        return view('livewire.show-reservations');
    }

    public function hallChanged()
    {
        $this->showTable = true;
    }
}

Must be missing something obvious.

10
  • Doesn't work at all, trying put $this->emit('hallChanged') everywhere ;D Commented Oct 5, 2020 at 6:54
  • Do you enter the updatedHallId() method when the field is changed? Add a dd('Test'); or similar in that method. Commented Oct 5, 2020 at 7:56
  • There's not really a need for wire:change, because you just listen for the updated event for that property from the component. Commented Oct 5, 2020 at 7:57
  • dd() in updatedHallId indeed working but this part seams not: $this->emit('hallChanged', $value); Or maybe something wrong with $listeners Commented Oct 5, 2020 at 9:32
  • And both components are on the same page? They cannot emit events to other users or other pages. You need broadcasting for that. Commented Oct 5, 2020 at 9:37

3 Answers 3

20

use wire:change

<select id="hall" wire:model="hall_id" wire:change="change">...</select>

then in component

In ShowReservationForm.php

public function change()
{
     $this->emit('hallChanged'); 
}

then you can listen it on ShowReservations component ref link https://laravel-livewire.com/docs/2.x/events

in ShowReservations.php

 protected $listeners = ['hallChanged' => 'change'];

public function change()
{
   $this->showTable = true;
}
Sign up to request clarification or add additional context in comments.

3 Comments

I actualy don’t want to use JS, It would be very awkward. And I use version 2 of livewire.
by the way what you are doing with showTable ? you can directly do @if(!empty($hall_id)) table @endif
That table is in another component ant initial state is false and yes I'm doing simple @if statement. So what I'm trying to do is to change that $showTable property to true.
4

It's turns out that when receiving event, property value must not be bool?

This will not work:

public $showTable = false;
...
public function hallChanged()
    {
        $this->showTable = true;
    }

This will work

public $showTable = 0;
...
public function hallChanged()
    {
        $this->showTable = 1;
    }

Comments

1

If the code not works, take a look about any [for example jQuery] handle for your select, maybe it handled by select2 script or so, if so - LiveWire will not work from scratch. The rigth minimal code is:

/resources/views/livewire/your-livewire-component.blade.php

<select wire:model="country">
    @foreach($items as $code => $country)
        <option value="{{ $code }}">{{ $country }}</option>
    @endforeach
</select>

/app/Http/Livewire/YourLivewireComponent.php

<?php
namespace App\Http\Livewire;
use Illuminate\Support\Facades\Log;
use Livewire\Component;
class YourLivewireComponent extends Component
{
    public $items;
    public $country; //necessary!
    public function mount($items)
    {
        $this->items = $items;
    }

    public function render()
    {
        return view('livewire.your-livewire-component', [
            'items' => ['ES' => 'Spain', 'FI' => 'Finland']
        ]);
    }

    public function updatedCountry($value)
    {
        Log::info('value='.print_r($value, 1));
    }
}

/resources/views/somelaraveltemplate.blade.php

<p>some HTML code</p>
@livewire('your-liveweire-component')

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.