Search code examples
javascriptlaravellaravel-livewire

How can I properly access and use the value obtained from a Laravel Livewire 3 event in JavaScript?


In my scenario, I'm listening to the 'update-selected-company' event in a Livewire component, and upon receiving the event, I update the 'company_id' property. The code appears to work correctly. However, I encounter difficulties in utilizing the received value from the event in my JavaScript code. Below is the relevant code snippet:

#[On('update-selected-company')]
public function updateCompany($id)
{
    $this->js(<<<'JS'
        setTimeout(() => {
            $wire.company_id = {{ $id }};
        }, 250);
    JS);
}

Despite the seemingly correct implementation, the code does not function as expected. How can I effectively retrieve and use the 'company_id' value obtained from the event in my JavaScript logic?

EDITED SECTION I have two components, Create and Company. Create has the following code:

<?php

namespace App\Livewire\Contacts;

use App\Models\Company;
use App\Models\Contact;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Locked;
use Livewire\Attributes\On;
use Livewire\Component;

class Create extends Component
{
  public $first_name;
  public $last_name;
  public $status;
  public $email;

  // #[Locked]
  public $company_id;

  #[Computed]
  public function companies()
  {
    return Company::get(['name', 'id']);
  }

  public function save()
  {
    $this->validate([
      'first_name' => 'required|string',
      'last_name' => 'required|string',
      'email' => 'nullable|email:rfc,dns|unique:contacts',
      'company_id' => 'required|exists:companies,id',
      'status' => 'required|in:active,in_active',
    ], [
      'company_id.exists' => 'The selected company isn\'t in the database.'
    ]);

    $contact = new Contact();

    $contact->first_name = $this->first_name;
    $contact->last_name = $this->last_name;
    $contact->email = $this->email;
    $contact->status = $this->status;
    $contact->company_id = $this->company_id;
    $contact->user_id = Auth::user()->id;

    $contact->save();

    $this->reset();

    return $this->redirect(Index::class);
  }

  #[On('update-selected-company')]
  public function updateCompany($id)
  {
    $this->js(<<<'JS'
      setTimeout(() => {
        $wire.company_id = $id;
      }, 250);
    JS);
  }

  public function render()
  {
    return view('livewire.contacts.create');
  }
}

The Company component has the following code:

<?php

namespace App\Livewire\Contacts;

use App\Models\Company as ModelsCompany;
use Livewire\Component;

class Company extends Component
{
  public $open = false;
  public $name;

  public function addCompany()
  {
    $this->validate([
      'name' => 'required|string',
    ]);

    $company = new ModelsCompany();

    $company->name = $this->name;

    $company->save();

    $this->reset('name');

    $this->dispatch('close', modal: 'create-company');
    $this->dispatch('update-selected-company', id: $company->id)->to(Create::class);
  }

  public function render()
  {
    return view('livewire.contacts.company');
  }
}

Both of these are modals. The Company modal gets opened when a user clicks on Create a company in the Create component when a company they are looking for isn't available in the available companies list. When a company is created the Company modal closes and then I need to update the company_id in the Create component to the newly created company and make it the current company in the select tag. Hope this helps.


Solution

  • So I figured out how to make this work. Here is how I did it, thanks to Wizzy from Github for pointing out that I should use heredoc instead of nowdoc:

    #[On('update-selected-company')]
     public function updateCompany($id)
     {
       $this->js(<<<JS
         let component = Livewire.getByName('contacts.create')[0]
    
         setTimeout(() => {
           component.set('company_id', $id);
         }, 50);
       JS);
     }