Reputation: 1406
I am in the process of trying out Laravel Livewire with a project for the first time. I am trying to build a fairly simple form with one set of cascading dropdowns - one input dependent on the other. But, when I try to pass an eloquent object to a component property, it is converted to a string so I can not access any of the object's properties.
I feel like there is something very simple I may be missing.
Here is my component code:
PostComponent.php
class PostComponent extends Component
{
public $manufacturers;
public $manufacturer = 'Select a Manufacturer';
public $cars;
public function mount()
{
$this->manufacturers = Manufacturer::orderBy('name')->get();
}
public function updated()
{
$this->cars = Car::where('manufacturer_id', $this->manufacturer->id)->get();
}
public function render()
{
return view('livewire.post-component');
}
Here is my blade file:
<label for="manufacturer">Manufacturer</label>
<select wire:model="manufacturer" id="manufacturer">
<option selected="selected" disabled>Select a Manufacturer</option>
@foreach($manufacturers as $selectableManufacturer)
<option value="{{ $selectableManufacturer }}">{{ $selectableManufacturer->name }}</option>
@endforeach
</select>
When I attempt to select a manufacturer in the dropdown, I can log the $manufacturer
and see that the value is
{"id":16,"name":"Manufacturer1","description":"lorem ipsum","created_at":"2020-06-26T23:44:37.000000Z","updated_at":"2020-06-26T23:44:37.000000Z"}
But when I try to get the id
of the manufacturer when attempting to select cars in the updated
lifecycle hook, I get the error
Trying to get property 'id' of non-object
Any idea as to why this is happening and how to fix it?
Upvotes: 2
Views: 12228
Reputation: 3870
Simply follow the documentation it is straight forward:
https://laravel-livewire.com/docs/2.x/properties#binding-models
Upvotes: -1
Reputation: 4849
You should sync the id
of the selected manufacturer and use that in an updated hook. Here is how you can do it.
class PostComponent extends Component
{
public $manufacturers;
public $manufacturer_id;
public $manufacturer = 'Select a Manufacturer';
public $cars;
public function mount()
{
$this->manufacturers = Manufacturer::orderBy('name')->get();
}
public function updatedManufacturerId()
{
$this->cars = Car::where('manufacturer_id', $this->manufacturer_id)->get();
}
public function render()
{
return view('livewire.post-component');
}
}
The frontend can remain same.
<label for="manufacturer_id">Manufacturer</label>
<select wire:model="manufacturer_id" id="manufacturer_id">
<option selected="selected" disabled>Select a Manufacturer</option>
@foreach($manufacturers as $selectableManufacturer)
<option value="{{ $selectableManufacturer->id }}">{{ $selectableManufacturer->name }}</option>
@endforeach
</select>
Upvotes: 1
Reputation: 1030
The issue with your implementation is that, in the select box what you echo out in the blade is a string
, not an object
, so wire modal will do its job by getting the value of the input event and sync it with the backend.
There are two ways that you can achieve your goal.
<label for="manufacturer_id">Manufacturer</label>
<select wire:model="manufacturer_id" id="manufacturer_id">
<option selected="selected" disabled>Select a Manufacturer</option>
@foreach($manufacturers as $selectableManufacturer)
<option value="{{ $selectableManufacturer->id }}">{{ $selectableManufacturer->name }}</option>
@endforeach
</select>
In the updated hook,
public $manufacturer_id;
public function updated()
{
$this->cars = Car::where('manufacturer_id', $this->manufacturer_id)->get();
}
json_decode()
function to make it an object and then access the id property as you have done. public function updated()
{
$manufacturer = json_decode($this->manufacturer);
$this->cars = Car::where('manufacturer_id', $manufacturer->id)->get();
}
But the healthy approach would be to use the id as the value.
Upvotes: 2