Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

SigalZ's avatar

Livewire - direct error message - not working

I need to add a validation error in a complex situation.

To do so, I thought I will have my own condition to check if there's an error and add the error to the errors manually.

Following the Livewire documentation, I have no success.

From the documentation:

"You can also add custom key/message pairs to the error bag.

$this->addError('key', 'message')"

And this:

"The validate() and validateOnly() methods should handle most cases, but sometimes you may want direct control over Livewire's internal ErrorBag.

Livewire provides a handful of methods for you to directly manipulate the ErrorBag.

From anywhere inside a Livewire component class, you can call the following methods:

// Quickly add a validation message to the error bag. $this->addError('email', 'The email field is invalid.');"

In my component:

protected $rules = 
    [
        'roastReportName' => 'required',
        'greenBeanId' => 'required',
        'roastTypeId' => 'required',
        'stickerId' => 'required',
        'weights.*.price' => 'numeric'
    ];

 public function storeBean()
    {    
        $this->validate();

        $this->addError('stickerId', 'This is a test.');
...
}

In my blade:

@if($errors->any())
    <div class="alert alert-danger">
        <p><strong>Opps Something went wrong</strong></p>
        <ul>
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
        </ul>
    </div>
@endif

I submit the form with errors, all the errors display besides the one I added manually.

From the documentation:

"// This will give you full access to the error bag.

$errors = $this->getErrorBag();

// With this error bag instance, you can do things like this:

$errors->add('some-key', 'Some message');"

I tried:

public function storeBean()
    {    
        $this->validate();

        // This will give you full access to the error bag.
       $errors = $this->getErrorBag();

       // With this error bag instance, you can do things like this:
       $errors->add('stickerId', 'Some message');

Error does not display

From the documentation:

Sometimes you may want to access the Validator instance that Livewire uses in the validate() and validateOnly() methods. This is possible using the withValidator method. The closure you provide receives the fully constructed validator as an argument, allowing you to call any of its methods before the validation rules are actually evaluated.

use Illuminate\Validation\Validator;

class ContactForm extends Component
{
    public function save()
    {
        $this->withValidator(function (Validator $validator) {

         $validator->after(function ($validator) {
                if ($this->somethingElseIsInvalid()) {
                    $validator->errors()->add('field', 'Something is wrong with this field!');
                }
            });
        })->validate();
    }
}

I tried:

public function storeBean()
    {    
        $this->validate();

        $this->withValidator(function (Validator $validator) {

            $validator->after(function ($validator) {
                    //no condition here, just want to test if the error is being added
                    $validator->errors()->add('stickerId', 'Something is wrong with this field!');
            });
        })->validate();
...}

Nope.

What am I missing?

0 likes
17 replies
Snapey's avatar

have you tried throwing a validation error instead?

Snapey's avatar

@SigalZ I mean like

use Illuminate\Validation\ValidationException;
//

    if ($this->somethingElseIsInvalid()) {
        throw ValidationException::withMessages(['field' => 'Something is wrong with this field!']);
    }

1 like
SigalZ's avatar

@Snapey tried this:

public function storeBean()
    {    
        $this->validate();           
      
        if ($this->somethingElseIsInvalid()) {
            throw ValidationException::withMessages(['stickerId' => 'Something is wrong with this field!']);
        }
...
}

The error was not added

kokoshneta's avatar

As soon as you run $this->validate(), Livewire will run the whole validation process. If anything fails in that process, $this->validate() will throw a validation exception which Livewire catches. When it does that, it immediately stops execution and renders the component with the error bag from the validation.

So if you submit the form with errors and then run $this->validate() as the first thing in storeBean(), anything you put after $this->validate() will never be executed.

If you want to access the validator (as in your last example in the question), you have to remove $this->validate() from the beginning of storeBean(). Otherwise you’re first running a regular, default validation and then (if the first one succeeds) running the customised validation right after it.

If you just want to add an error to the error bag, do so before you run $this->validate().

SigalZ's avatar

@kokoshneta Thank you, I tried this now:

use Illuminate\Support\Facades\Validator;

class BeanForm extends Component
{    

	 public function storeBean()
    {
        $this->withValidator(function (Validator $validator) {
            $validator->after(function ($validator) {
            //no condition here, just want to test if the error is being added
                    $validator->errors()->add('stickerId', 'Something is wrong with this field!');
            });
        })->validate();
    }

Now I get this error:

Argument #1 ($validator) must be of type Illuminate\Support\Facades\Validator, Illuminate\Validation\Validator given
1 like
kokoshneta's avatar

@SigalZ That’s because your use clause at the top is wrong. You’re telling it to treat Validator as equivalent to Illuminate\Support\Facade\Validator, but when you’re type hinting, you want Illuminate\Validation\Validator.

SigalZ's avatar

@kokoshneta Ok, great, I am really thankful for your help.

If you don't mind and can help a bit more, I still have a problem. n

I have an array of inputs and I need to validate each set of these inputs and give errors on each one, so my code:

public function storeBean()
{
      $bagError = false;

      foreach($this->weights as $key => $val) {
          //Check every record, if the price is entered the selectedBag should be selected as well.
          if($val['price'] != '' && $val['selectedBag'] == '') {
              $this->withValidator(function (Validator $validator) use ($key) {
                    $validator->after(function ($validator)  use ($key) {
                           $validator->errors()->add('weights.'.$key.'.selectedBag', 'Please select a bag');
                    });
            })->validate();
                
            $bagError = true;               
         }
  }
        
        if(!$bagError)
            $this->validate(); 
...
}

This of course quits after the first error so the user get the error only on one line for these inputs and not on all of the ones where he captured price without selecting a bag.

I also tried:

foreach($this->weights as $key => $val) {
            if($val['price'] != '' && $val['selectedBag'] == '') {
                $this->withValidator(function (Validator $validator) use ($key) {
                    $validator->after(function ($validator)  use ($key) {
                        $validator->errors()->add('weights.'.$key.'.selectedBag', 'Please select a bag');
                    });
                });
            }
        }

But this added the last error of the selectedBag over the first one, so I only got the error on the last input.

Again, thank you very much for all your help.

kokoshneta's avatar

@SigalZ The best thing would be to just use basic validation and set up your rules to handle everything properly, but I can’t really figure out exactly how exactly you want to validate this data.

Can you please describe what the user input looks like and what the logic behind the validation is (e.g., “if the user chooses option A in dropdown 1, then the input field X must be filled in”, etc.)? As best I can tell, the user can choose a number of weights; if they do, and the price for each weight is set, then the selectedBag of that weight must also be set. Is that correct?

SigalZ's avatar

@kokoshneta You are correct.

I am building an array of fields like this: hard coded text for weight

input for price

dropdown of bags

The weights and bags are coming from a table called: bags in the database.

So if I have in the bags table records like this:

weight: 250g color: Black

weight 250g color: Silver

weight 1kg color: Black

The user will see 2 lines, one for each available weight:

Label 250g, Input price, dropdown bags (Black 250g, Silver 250g)

Label 1kg, Input price, dropdown bags (Black 1kg)

If the user puts a price in any of these lines he needs to select a bag as well.

I do not default the bags dropdowns to the first value because we already have "stupid" users that keeps making the same mistake and just use whatever is defaulted in the dropdown instead of selecting the needed value.

My form validation is built with Bootstrap where an error is displayed under each field, so I want it to be consistent and appear under these prices / bags dropdowns as well.

I hope I made it clearer?

kokoshneta's avatar
Level 27

@SigalZ All right, that makes sense. That should be fairly easy to do with the standard rules, without having to access the validator or anything like that. Essentially, I think you just need a required_with rule for your bag dropdown, dependent on the price field:

protected $rules = 
    [
        'roastReportName' => 'required',
        'greenBeanId' => 'required',
        'roastTypeId' => 'required',
        'stickerId' => 'required',
        'weights.*.price' => 'numeric',
		'weights.*.selectedBag' => 'required_with:weights.*.price'
    ];

// Add a message to appear if price is given but not bag
protected $messages = [
	'weights.*.selectedBag.required_with' = "You must select a bag if you provide a price"
];

 public function storeBean()
    {    
        $this->validate();
		...
	}
}
1 like
SigalZ's avatar

@kokoshneta OMG! and I know this rule. Dear god, what was I thinking??? LOL well, at least I learnt some new things.

You are a star, thank you for all your kind help.

I declare a momentarily insanity, and I'm sticking to it...

1 like
SigalZ's avatar

@kokoshneta One problem with this, it does not work if there's a Zero in the price field.

kokoshneta's avatar

@SigalZ You mean if the user sets the price to be zero (I assume it works fine if the price is 10 or 100)?

What should happen if price is zero? Should it be possible to set it to be free or not?

SigalZ's avatar

@kokoshneta The price should not be zero. Hmmm, actually, I do have a validation for the price so it can't be zero. Sorry, got totally lost with this coding. I think all is good now.

Please or to participate in this conversation.