Livewire, Alpine and validation

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
1 Like

Found no other solution, so I’ve refactored my inputs to Livewire only.

Caleb just published a Livewire alpine package. This may solve your problem. https://github.com/livewire/alpine-plugin/

2 Likes