RedEclipse
RedEclipse

Reputation: 123

Validate forms with laravel bag

I've got multiple forms with validation on one page, so once of it had been submitted it displays validation errors on every form. I want to prevent that, so if form 1 was submitted, I want to display validation messages only for form 1, without form 2.

So that's what I'm currently come up:

Controller

    public function composeMail(Request $request)
    {

        $validator = Validator::make($request->all(),
            [
                'subject' => 'max:40|regex:/^[A-Za-z]+$/u',
                'body' => 'required|min:1|max:1000|regex:/^[A-Za-z0-9]+$/u'
            ],
            [
                'subject.max' => 'Subject can be maximum 40 symbols length.',
                'subject.regex' => 'In subject Only numbers and latin letters is allowed.',
                'body.required' => 'Message cannot be empty.',
                'body.min' => 'Message shall contain at least one character.',
                'body.max' => 'Message can be only 10000 symbols length.',
                'body.regex' => 'In message only numbers and latin letters is allowed.',
        ])->validateWithBag('email');

        return redirect()->back()->withErrors($validator);

Views

                @if ($errors->any())
                    <div class="alert">
                        <ul>
                            @foreach ($validator->email as $error)
                                <li>{{ $error }}</li>
                            @endforeach
                        </ul>
                    </div>
                @endif

Currently it just returns to the page and nothing happens, validation doesn't work and doesn't prints out anything... Can you tell me what's wrong with it?

Upvotes: 0

Views: 6830

Answers (3)

Peppermintology
Peppermintology

Reputation: 10220

The behaviour you're seeing is expected. $errors->any() inspects the default message bag and does not take named error bags into consideration.

Illuminate\Support\ViewErrorBag.php

/**
 * Determine if the default message bag has any messages.
 *
 * @return bool
 */
public function any()
{
    return $this->count() > 0;
}

/**
 * Get the number of messages in the default bag.
 *
 * @return int
 */
public function count()
{
    return $this->getBag('default')->count();
}

So to show errors for your specific forms with named bags, you need to access them as such:

@if ($errors->namedBag->any())
  <ul>
  @foreach($errors->namedBag->all() as $error)
    <li>{{ $error }}</li>
  @endforeach
  </ul>
@endif

If you don't want to place all the validation error messages together but perhaps want to put error messages specific to a field underneath the field, you can provide the get() method on the named error bag with the name of the field to get just the errors you want:

@if ($errors->namedBag->get('name'))
  <ul>
  @foreach($errors->namedBag->get('name') as $error)
    <li>{{ $error }}</li>
  @endforeach
  </ul>
@endif

Upvotes: 0

bhucho
bhucho

Reputation: 3420

You are using ->validateWithBag('email'); to get automatic redirection see Automatic redirection,
but you are still passing return redirect()->back()->withErrors($validator, 'email');.

Also you should redirect when it fails,

if ($validator->fails()) {
            return redirect()
                        ->back()
                        ->withErrors($validator, 'email');
                        
        }

Also If you want automatic redirection you can directly use

$validatedData = $request->validateWithBag('email', [
                'subject' => 'max:40|regex:/^[A-Za-z]+$/u',
                'body' => 'required|min:1|max:1000|regex:/^[A-Za-z0-9]+$/u'
            ],
            [
                'subject.max' => 'Subject can be maximum 40 symbols length.',
                'subject.regex' => 'In subject Only numbers and latin letters is allowed.',
                'body.required' => 'Message cannot be empty.',
                'body.min' => 'Message shall contain at least one character.',
                'body.max' => 'Message can be only 10000 symbols length.',
                'body.regex' => 'In message only numbers and latin letters is allowed.',
        ]);

Upvotes: 1

Donkarnash
Donkarnash

Reputation: 12845

Guess you need to send the name of the error bag too

public function composeMail(Request $request)
    {

        $validator = Validator::make($request->all(),
            [
                'subject' => 'max:40|regex:/^[A-Za-z]+$/u',
                'body' => 'required|min:1|max:1000|regex:/^[A-Za-z0-9]+$/u'
            ],
            [
                'subject.max' => 'Subject can be maximum 40 symbols length.',
                'subject.regex' => 'In subject Only numbers and latin letters is allowed.',
                'body.required' => 'Message cannot be empty.',
                'body.min' => 'Message shall contain at least one character.',
                'body.max' => 'Message can be only 10000 symbols length.',
                'body.regex' => 'In message only numbers and latin letters is allowed.',
        ])->validateWithBag('email');

        return redirect()->back()->withErrors($validator, 'email');
}

And in blade view the errors from named bag need to be accessed as

@if ($errors->any())
    <div class="alert">
         <ul>
             @foreach ($errors->email as $error)
                 <li>{{ $error }}</li>
             @endforeach
         </ul>
    </div>
@endif

Upvotes: 0

Related Questions