livewire: Validation errors are not flashed to session

If a validation error happens in Livewire, the ViewErrorBag (or MessageBag?) is not flashed to session as Laravel validation normally does (check https://laravel.com/docs/master/validation#quick-displaying-the-validation-errors). This means that when validations occur inside Livewire components, we can’t access “session()->get(‘errors’)”.

This is a problem for new Laravel 7 components syntax. For example, when creating a custom input, I want to use the @error blade directive inside the component. For this to work, I need to set the error bag in a public $errors property, so it gets injected inside the component. Something like this:

class Input extends Component
{
    public string $name;
    public string $label;
    public string $type;
    public $errors;

    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct(string $name, string $label, string $type = 'text')
    {
        $this->name = $name;
        $this->label = $label;
        $this->type = $type;
        $this->errors = session()->get('errors') :? new ViewErrorBag(); //This does not work, since session()->get('errors') is null
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\View\View|string
     */
    public function render()
    {
        return view('components.input');
    }
}

For now, we are doing this:

Input.php (component class):

class Input extends Component
{
    public string $name;
    public string $label;
    public string $type;
    public $errors;

    /**
     * Create a new component instance.
     *
     * @return void
     */
    public function __construct(string $name, string $label, $errors, string $type = 'text')
    {
        $this->name = $name;
        $this->label = $label;
        $this->type = $type;
        $this->errors = $errors;
    }

    /**
     * Get the view / contents that represent the component.
     *
     * @return \Illuminate\View\View|string
     */
    public function render()
    {
        return view('components.input');
    }
}

input.blade.php (view):

...
<x-input name="email" type="email" label="E-mail" :errors="$errors"/> // Passing $errors on every component isn't a good solution
...

I tested and I can confirm that just changing the following code inside Livewire\Component@output method solves this issue. I submitted the PR #622 which does this:

public function output($errors = null)
{
        ...
        ...
        $errors = (new ViewErrorBag)->put('default', $errorBag); //<- add this

        $view->with([
            'errors' => $errors, //<- change this
            '_instance' => $this,
        ] + $this->getPublicPropertiesDefinedBySubClass());

        session()->flash('errors', $errors); //<- add this
        ...
        ...
}

Thanks!!

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 22 (15 by maintainers)

Most upvoted comments

@gjm this is Exactly what my PR, mentioned on this issue, fixes 😃 Just waiting for it to be merged too

Hello @mokhosh I guess it is another problem. I think you need to find a way of reseting the validations once you have closed your modal. Livewire has a reset method (not documented yet) and a $refresh method also that you can try calling using Javascript on modal close/open. Just some tips, you could try if you want.

I’ve just opened PR #704 that fixes the issue of $errors not being available to nested components.