Validation errors in AJAX mode

2019-03-07 21:34发布

Currently I use this to display validation errors via ajax:

            if (data.validation_failed == 1)
            {
                var arr = data.errors;
                $.each(arr, function(index, value)
                {
                    if (value.length != 0)
                    {
                        $("#validation-errors").append('<div class="alert alert-error"><strong>'+ value +'</strong><div>');
                    }
                });
                $('#ajax-loading').hide();
                $("#validation-errors").show();
            }

It works fine, does exactly what I need.

The problem is what I have to do to transport the errors from laravel to ajax:

    $rules = array( 
        'name'  => 'required',
        'password' => 'required'
    );

    $v = Validator::make(Input::all(), $rules);

    if ( ! $v->passes())
    {

    $messages = $v->messages();

    foreach ($rules as $key => $value)
    {
        $verrors[$key] = $messages->first($key);
    }

        if(Request::ajax())
        {                    
            $response_values = array(
                'validation_failed' => 1,
                'errors' => $verrors);              
        return Response::json($response_values);
        }
        else
        {
        return Redirect::to('login')
            ->with('validation_failed', 1)
            ->withErrors($v);
        }       

    }

If I want to have the field names as key, I have to iterate $rules, but even if I don't use field names as key, yet I have to iterate error messages to construct $verrors.

How could I convert $v->messages() to the equivalent of $verrors without the need to iterate? Since Response::json() is expecting an array instead of an object.

6条回答
SAY GOODBYE
2楼-- · 2019-03-07 21:50

Laravel 5 returns validation error automatically

for that you just need to do following thing,

Controller:

public function methodName(Request $request)
{
    $this->validate($request,[
        'field-to-validate' => 'required'
    ]);

    // if it's correctly validated then do the stuff here

    return new JsonResponse(['data'=>$youCanPassAnything],200);
}

View:

         $.ajax({
            type: 'POST',
            url: 'url-to-call',
            data: {
                "_token": "{{ csrf_token() }}",
                "field": $('#field').cal()
            },
            success: function (data) {
                console.log(data);
            },
            error: function (reject) {
                if( reject.status === 422 ) {
                    var errors = $.parseJSON(reject.responseText);
                    $.each(errors, function (key, val) {
                        $("#" + key + "_error").text(val[0]);
                    });
                }
            }
        });

you can build for each validation field one <span> tag with id as field name and suffix _error so it will show validation error with above logic like as follow,

<span id="field_error"></span>

Hope it helps :)

查看更多
唯我独甜
3楼-- · 2019-03-07 21:51

I'm using Laravel 5.1 by the way but i think the fundamentals of this should apply to other versions. Laravel sends back the validation error response automatically. You can just do the following in your controller:

public function processEmail(Request $request)
{
    $this->validate($request, [
        'email' => 'required|email'
    ]);
    return response()->json(['message'=>'success']);
}

Then in your javascript (i'm using jQuery here):

var params = {email: 'get-from-form-input@test.com'};
$.ajax({
    url: '/test/example',
    method: 'POST',
    data: params
})
.done(function( data ) {
    // do something nice, the response was successful
})
.fail(function(jqXHR, textStatus, errorThrown) {
    var responseMsg = jQuery.parseJSON(jqXHR.responseText);
    var errorMsg = 'There was a general problem with your request';
    if (responseMsg.hasOwnProperty('email')) {
        errorMsg = responseMsg.email;
        console.log(errorMsg);
    }
    // This will help you debug the response
    console.log(jqXHR);
    console.log(textStatus);
    console.log(errorThrown);
});

If you look at the output on the console you'll soon see how to grab anything you want from the response sent back by Laravel. In that response the error messages are in json as key-value pairs where the key is the name of the field that failed validation, in my example 'email'. Remember to ensure the ajax route is set up in your routes.php file and the method (get/post) matches that in the javascript.

查看更多
一纸荒年 Trace。
4楼-- · 2019-03-07 21:59

The easiest way is to leverage the MessageBag object of the validator. This can be done like this:

// Setup the validator
$rules = array('username' => 'required|email', 'password' => 'required');
$validator = Validator::make(Input::all(), $rules);

// Validate the input and return correct response
if ($validator->fails())
{
    return Response::json(array(
        'success' => false,
        'errors' => $validator->getMessageBag()->toArray()

    ), 400); // 400 being the HTTP code for an invalid request.
}
return Response::json(array('success' => true), 200);

This would give you a JSON response like this:

{
    "success": false,
    "errors": {
        "username": [
            "The username field is required."
        ],
        "password": [
            "The password field is required."
        ]
    }
}
查看更多
We Are One
5楼-- · 2019-03-07 22:03

There is a better way to handle validation errors when using Ajax request.

Create a Request class as usual, for example UploadFileAjaxRequest:

public function rules()
{
    return [
        'file' => 'required'
    ];
}

Use it in a controller method:

public function uploadFileAjax(UploadFileAjaxRequest $request)

If there is any error, it will return an array of errors which you can use in JS:

$.ajax({
    ....
    error: function(data) {
        var errors = data.responseJSON; // An array with all errors.
    }
});
查看更多
在下西门庆
6楼-- · 2019-03-07 22:05

I handled it using this way for laravel 5.5

Html code

<div class="form-group  padding">
  <label for="">Kalyan Mandap Name <span class="text-danger">*</span></label>
  <input type="text" class="form-control" placeholder="Enter Kalyan Mandap Name" id="mandapName" name="mandapName" value = "<?php echo (isset($mandapDetails['vchKalyanMandapName'])) ? $mandapDetails['vchKalyanMandapName'] : ""; ?>" required="required">
  <span class="text-danger">{!! $errors->first('mandapName', ':message') !!} </span>
</div>

Controller validation code

 // Validate form data
    $validatedData = request()->validate([
      'mandapName' => 'required',
      'location' => 'required',
      'landmark' => 'required',
      'description' => 'required',
      'contactNo' => 'required',
      'slug' => 'required',
      'functional' => 'required'
    ]);

And in javascript

     $.ajax({
        //.....Your ajax configuration
        success: function (data) {
            // Success code

        },
        error: function (request, status, error) {
            $('[name="mandapName"]').next('span').html(request.responseJSON.errors.mandapName);
            //.......
        }
    });
查看更多
家丑人穷心不美
7楼-- · 2019-03-07 22:10

In the ajax response trying something like

    .fail(function( data ) {
        var response = JSON.parse(data.responseText);
        var errorString = '<ul>';
        $.each( response.errors, function( key, value) {
            errorString += '<li>' + value + '</li>';
        });
        errorString += '</ul>';
查看更多
登录 后发表回答