livewire: Model variable resets or doesn't carry the state after every request
Description
A Model variable resets at every request / attempt to add attributes to it.
Exact steps to reproduce
I have a User model stored in a public variable $user. I set the initial value from the mount method.
On a different function, that is called using $listeners, I would add some properties, such as a relationship, a database value, etc. No matter what I add (or even do nothing to it), the variable clears the previous state and re-initialise again. This is an issue only with variables that are used for Models.
Stripped-down, copy-pastable code snippets
<?php
class Create extends Component
{
public User $user;
public $userArray = [];
protected $listeners = [
'step1:completed' => 'setStep1Data',
'step2:completed' => 'setStep2Data',
'step3:completed' => 'setStep3Data',
'step4:completed' => 'setStep4Data',
];
public function aNormalFunctionCalledDirectlyFromTheComponentPage()
{
// Whatever you do here, the variable $this->user re-initialise itself with an empty object.
}
public function setStep1Data( $contact )
{
// This works, it sets the contact relation...
$this->user->setRelation('contact', new Contact($contact));
// The state of userArray is not getting reset. It works fine, as intended.
// For a moment, the user variable state is working fine
$this->userArray = array_merge($this->user->toArray(), $this->userArray);
// BUT once the function terminates, it will have ONLY the contact relation set,
// the name property set by the mount() method is gone.
}
public function setStep2Data( $email )
{
// This works, it sets the email property
$this->user->email = $email;
// The state of userArray is not getting reset. It works fine, as intended.
// For a moment, the user variable state is working fine
$this->userArray = array_merge($this->user->toArray(), $this->userArray);
// BUT once the function terminates, it will have ONLY the email property set,
// the contact relation set by the setStep1Data() method is gone.
}
public function setStep3Data( $data )
{
// ...
}
public function setStep4Data( $data )
{
// ...
}
public function mount()
{
$this->user = new User();
$this->user->name = 'John Doe';
$this->userArray = array_merge($this->user->toArray(), $this->userArray);
}
public function render()
{
return view('livewire.users.create');
}
}
Context
- Livewire version: [2.2.7]
- Laravel version: [8.6.0]
- Browser: [Chrome, Safari]
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 1
- Comments: 19 (7 by maintainers)
Hi, I’m also experiencing this bug(?). Is there an upcoming fix for this?
From reading this issue I understand that you need to store the “model state” as an array, since a model won’t work.
This is however quite the workaround when you want to create multistep forms for example.
I am aware of this, the reason why I’ve wrote a specific function to change the property value is to show how Livewire resets the
$usermodel before each request. I believe this is an unintended behaviour, but I might be wrong and this is the way it is.Thanks for the advise, I might struggle a bit as I love working with Objects rather than arrays, especially when there is a relationship involved.
My scope was to build the Model object step by step (don’t look at the examples, it’s more complex than that), such as adding properties and relationships of any type (hasOne, hasMany, etc). and at the end, create it in one go.
Thank’s so much for your help though, you’ve been amazing trying to help me. Hopefully this thread is going to be helpful for others too.
Now I got what you’re trying to achieve. Arrays don’t save information on model data. If you’re planning to keep information for multiple models, then your only option at the moment is to save that information as a normal array, and later on process it as a model for DB persistence.
Checkout this example playground.
As a temporary solution (I might leave it for good though), I’m saving the user model on the session driver - and it works perfectly.
Looks like you’re missing your
protected $rulesattribute, defining the$uservalidation properties. It is specified in Livewire’s Documentation that you need to provide a$rulesproperty for your component, otherwise, errors may arise.In your example, you want to keep the name and email of the user, so your
$rulesproperty should be specified like:Could you try this and comment if it works?