I really would like to only use Livewire and alpine.js in all of my applications. I hope @calebporzio can make them interact seamlessly soon. Maybe it is already and am I doing something wrong, or it’s not possible and I want too much. Anyway: I’m running into an issue with Livewire, Alpine and validation.
If a Livewire validation error is triggered the current state of an alpine data property is reset/lost.
Code to reproduce (or better understand) my issue:
class Alpine extends Component
{
public $first_name;
public function mount(){
$this->first_name = 'My first name';
}
public function render()
{
return view('livewire.alpine');
}
public function updated($field)
{
$this->validateOnly($field, $this->validations());
}
private function validations()
{
return [
'first_name' => 'required|min:2',
];
}
}
livewire/alpine.blade.php :
<div>
<div class="md:flex md:items-center mb-1 md:mb-3" x-data="edit()">
<div class="md:w-1/3">
<label class="block md:text-left mb-1 md:mb-0 pr-4" for="first_name" @click="toggle()">First name <span x-text="edit"></span></label>
</div>
<div class="md:w-2/3 relative">
<input
class="appearance-none border-2 border-white rounded w-full py-2 px-2 text-gray-700 leading-tight outline-none" :class="{ 'border-blue-700' : edit }"
@if($errors->has('first_name')) class="border-red-500" @elseif($this->first_name) class="border-green-500" @endif
wire:model.lazy="first_name"
x-bind:required="edit" x-bind:readonly="!edit"
placeholder="First name"
/>
<div x-show="edit" class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-400">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M0 11l2-2 5 5L18 3l2 2L7 18z"/>
</svg>
</div>
<div x-show="!edit" class="absolute inset-y-0 right-0 flex items-center px-2 text-gray-400" @click="edit = true">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<path d="M12.3 3.7l4 4L4 20H0v-4L12.3 3.7zm1.4-1.4L16 0l4 4-2.3 2.3-4-4z"/>
</svg>
</div>
@error('first_name')<div class="-mt-1 bottom-1 left-0 absolute block text-red-500 text-xs italic">{{ $message }}</div> @enderror
</div>
</div>
</div>
@push('scripts')
<script>
function edit() {
return {
edit: false,
toggle() {
this.edit = !this.edit
},
}
}
</script>
@endpush