Search code examples
laravellaravel-livewire

Laravel Livewire getting error message from validator in component


in my register form i have a username input field into the form and i want to only validate it with this below rule:

'required|regex:/^[a-zA-Z]+$/u|min:5|max:15|unique:users'

and i want to get validation error and send it with another way to view instead of using bags message in view like with Laravel implementation. for example:

<input type="text" class="form-control"
       name="username"
       wire:model="username"
       value="{{old('username')}}">

component:

    public function updatedUsername($username)
    {
        //$validator = $this->validate(['username' => 'required|regex:/^[a-zA-Z]+$/u|min:5|max:15|unique:users']);

        $validator = $this->validateOnly($username,['username' => 'required|regex:/^[a-zA-Z]+$/u|min:5|max:15|unique:users']);

        if ($validator->fail()) {
            // ...
        } else {
            // ...
        }
    }

in this Component how can i get validation error?


Solution

  • When using validate()/validateOnly(), an exception will be thrown if the validation fails. Laravel will intercept this validation error to handle it in the blade-template, for features like @error('fieldName').

    In order to hook into the validation in "real-time" with Livewire, you need to catch that exception. To get the real-time validation with @error('fieldName'), you should also re-throw the exception once you are done.

    public function updated($field)
    {
        try {
            $this->validateOnly($field);
        } catch (\Illuminate\Validation\ValidationException $e) {
            // Do your thing and use $validator here
            $validator = $e->validator;
    
            // ...
    
            // Once you're done, re-throw the exception
            throw $e;
        }
    }
    

    As you probably may have noticed, there is no definition of any of the rules here. That's because they should be defined in the protected property $rules your class (unless you have a really compelling reason to leave it out of the global ruleset for that component).

    class Foo extends Component
    {
        protected $rules = [
            'username' => 'required|regex:/^[a-zA-Z]+$/u|min:5|max:15|unique:users'
        ];
        
        // ....
    }
    

    If you ever need to introduce other properties or use functions into the rules, you can remove the property and declare a rules() method instead - this isn't as well documented, so might be a bit obscure.

    class Foo extends Component
    {
        public function rules() 
        {
            return [
                'username' => 'required|regex:/^[a-zA-Z]+$/u|min:5|max:15|unique:users'
            ];
        }
    }
    

    Sidenote: Instead of using a regex, you may want to use the alpha rule instead.