phplaravel-livewire

How to hook event of validation error in livewire 2?


Reading how validations work at https://laravel-livewire.com/docs/2.x/input-validation I did not find if there is a way in livewire 2 when I have validation error to hook event as I need to send dispatchBrowserEvent event to show message with toastr ?

My form is rather big and val;idation field can be out of screen and I want to pay attention of user that there are validation errors...

Updated Block # 1: You propose to get rid of livewire validate method and use laravel validate methods, which are written here https://laravel.com/docs/8.x/validation, like :

   $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        if ($validator->fails()) {
   ...
   
       

In my conmponent I define all variables under 1 variable $form :

public $form
    = [
        'name'               => '',
        'state_id'           => '',

 ...
 

public function firstStepSubmit()
{
    $rules = [
        'name'         => 'required',
        'state_id'     => 'required',
    ];

    $validation = Validator::make( $this->form, $rules, Hostel::getValidationMessagesArray());
    $failed     = $validation->fails();
    if ($failed) {
        $errorMsg = $validation->getMessageBag();
        $focus_field = array_key_first($errorMsg->getMessages());

        $this->dispatchBrowserEvent('PersonalPageMessageWarning', [
            'title'   => 'Personal Hostel',
            'message' => 'Your hostel has invalid data !',
            'focus_field' => str_replace('form.', '', $focus_field ),
        ]);

        $validation->validate(); // What for this line ? Looks like we really need it ?
        return;
    }

    $this->currentStep = 2;
} // public function firstStepSubmit()

 
 
  1. // What for is

    $validation->validate(); 
    

line inside of failed block ? Do we really need it ?
2) moving to laravel original methods sems for me as step back... Are there some livewire hooks/methods for it ?

Thanks in advance!


Solution

  • I got a solution to that. Let's say you have next:

    // in blade
    <div class="col-md-6 flex-row">
       <label for="name">Name</label>
       <input id="name" type="text" class="form-control flex-row" wire:model="name">
       @error('name') <span class="error" style="color: #ff0000">{{ $message }}</span> @enderror
    </div>
    <div class="col-md-6 flex-row">
       <label for="last_name">Name</label>
       <input id="last_name" type="text" class="form-control flex-row" wire:model="last_name">
       @error('last_name') <span class="error" style="color: #ff0000">{{ $message }}</span> @enderror
    </div>
    .... // all the rest of elements
    
    //in component
    public $name, $last_name; 
    // the rest of properies
    
    public function store()
    {
        $validation = Validator::make([
           'name' => $this->name,
           'last_name' => $this->last_name,
            .....
        ], $this->rules());
    
        if ($validation->fails()) {
           $errorMsg = $validation->getMessageBag();
           $this->dispatchBrowserEvent('focusErrorInput',['field' => array_key_first($errorMsg->getMessages())]);
           $validation->validate();
        }
    
       //... other code
    

    now, if validation fails, the above validation checks dispatch and event with all the non-validated fields and in the blade's script tag handle the element focus in order of the error bag field. So, if the element is out of windows this will be focused

    <script>
    window.addEventListener('focusErrorInput', event => {
       var $field = '#' + event.detail.field;
       $($field).focus()
    })
    </script>