I have a property called public $items = []
. This can have multiple nested arrays, ie: $items.1, $items.2, $items.3
and so on. Each of these sub arrays needs to hold at least two pieces of data.
$items[1]['prop1'] = "value 1"; $items[1]['prop2'] = "value 2"; $items[2]['prop1'] = "value 1"; $items[2]['prop2'] = "value 2";
My issue is that in my view, I have two inputs bound to these sub properties.
I then add a new array entry based on this input. So if the user enters a certain thing in prop1, the array will contain an auto-generated element based on this input.
Now here’s the issue. When I change prop1
and capture it within the updatedItems
lifecycle hook, it’s correct. But when I change prop2
, it overwrites prop1
and the array only ever holds one value.
public function updatedItems($value, $nested) { $nestedData = explode(".", $nested); // Get the nested property that was changed. this will yield a string formated as "1.prop1" or "2.prop1" // Let's pretend that the $value variable says "value 1" and the $nested variable is "1.prop1" if ($nestedData[1] == 'prop1') { $this->items[$nestedData[0]]["secondary_value"] = 'secondary value'; // This should yield an items array that looks like this: items[1]['secondary_value'] = 'secondary value' } if ($nestedData[1] == 'prop2') { $this->items[$nestedData[0]]["third_value"] = 'third value'; // This should yield an items array that looks like this: items[1]['third_value'] = 'secondary value' } }
My expectation is that I would get an items
array that looks like this:
$items = [ "1" =['prop1' => 'value 1', 'secondary_value' => 'secondary value'], "2" =['prop2' => 'value 1', 'third_value' => 'third value'] ]
But no matter what I do, the items
array ONLY holds one value, the most recent one that was changed. So if I change prop1 first, then change prop2, the array will ONLY contain prop2 and it will not append to the array but basically recreate the whole array containing only that value.
I’ve looked at multiple other questions that suggest adding a $rules
property which I have defined but that still doesn’t solve the issue. I’ve even tried setting a session variable but that seems to have the same issue where it gets over written every time. Does livewire use some sort of session system that conflicts with laravels native one? Any help on getting this data to persist so that my array can hold the values of input1 and input2 at the same time would be greatly appreciated.
View
<tr> <td colspan="5"> <select wire:model="items.1.right_eye_brand"> <option value=""></option> @foreach ($sortedItems as $o) <option value="{{ $o }}">{{ $o->brand }}</option> @endforeach </select> </td> </tr> <tr> <td colspan="5"> <select wire:model="items.1.left_eye_brand"> <option value=""></option> @foreach ($sortedItems as $o) <option value="{{ $o }}">{{ $o->brand }}</option> @endforeach </select> </td> </tr>
Advertisement
Answer
The problem seems to be related to Livewire life cycle.
The problem
So I was able to reproduce the problem using laravelplayground.com. Here:
Short Answer
Don’t dump/dd inside updatedItems
.
Long Answer
In fact, items
is not correct when dumping items updatedItems
. But, the items
should be correct if you dump inside render
method.
I gonna search deeply to understand why it’s happening. But I guess there is some kind of merge with the original items
and the items
used in updatedItems method, and the merge happens update*
methods run and before render
is called.
I did another example in laravel playground, and it shows up the items content in view component and as you can see the data returned is always correct.