5
votes

I am using laravel 5.2,my question is:
How to show validation errors when submitting form with ajax ?

For example:
When ajax is not used,if the title field is not filled in, when submitting,there is an information :
"The title field is required."
And, when ajax is used,how to show the information above.

View:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="csrf-token" content="{{ csrf_token() }}">
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.bootcss.com/tether/1.1.1/css/tether.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
    <form id="formArticle" class="form-horizontal" role="form">
        <fieldset class="row form-group">
            <label class="col-xs-2 control-label">Title:</label>
            <div class="col-xs-10">
                <input id="title" name="title" type="text" class="form-control"
                       value="{{ old('title') }}">
                <span class="help-block"><strong></strong></span>
            </div>
        </fieldset>

        <fieldset class="row form-group">
            <label class="col-xs-2 control-label">Content:</label>
            <div class="col-xs-10">
                <input id="content" name="content" type="text" class="form-control"
                       value="{{ old('content') }}">
                <span class="help-block"><strong></strong></span>
            </div>
        </fieldset>

        <fieldset class="row form-group">
            <label class="col-xs-2 control-label" for="photo">Photo:</label>
            <div class="col-xs-10">
                <input id="photo" name="photo" type="file" class="form-control-file">
                <span class="help-block"><strong></strong></span>
            </div>
        </fieldset>
        <fieldset class="form-group">
            <div class="col-xs-12">
                <button id="submit" type="submit" class="btn btn-primary">Submit</button>
            </div>
        </fieldset>
    </form>
    <div class="alert alert-success" role="alert" hidden>
        upload successfully
    </div>
</div>
<script src="https://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/tether/1.1.1/js/tether.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/js/bootstrap.min.js"></script>

</body>
</html>

Javascript:

<script>
    $(function () {
        var articleData = new FormData($('#formArticle')[0]);


        $(document).on('submit', '#formArticle', function (e) {
            e.preventDefault();

            $('input+span>strong').text('');
            $('input').parent().parent().removeClass('has-error');

            $.ajaxSetup({
                headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                }
            });

            $.ajax({
                        type: "POST",
                        url: "{{ url('article/') }}",
                        dataType: 'json',
                        processData: false,
                        contentType: false,
                        cache: false,
                        data: articleData
                    })
                    .done(function (data) {
                        $(".alert-success").prop("hidden", false);
                    })
                    .fail(function (data) {
                        $.each(data.responseJSON, function (key, value) {
                            var input = '#formArticle input[name=' + key + ']';
                            $(input + '+span>strong').text(value);
                            $(input).parent().parent().addClass('has-error');
                        });
                    });
        });
    });
</script>

Controller:

    public function store(Requests\StoreArticleRequest $request)
    {
        $article = new Article;
        $article -> user_id = \Auth::id();

        $article->title = $request->title;
        $article->content = $request->content;

        $photo = $request->photo;
        $destinationPath = 'uploads/';
        $extension = $photo->getClientOriginalExtension();
        $photoName = \Auth::user()->id . '_' . time() . '.' . $extension;
        $photo->move($destinationPath, $photoName);
        $article -> photo = '/'.$destinationPath.$photoName;

        $article->save();
    }

StoreArticleRequest:

public function rules()
    {
        return [
            'title'=>'required',
            'content'=>'required',
            'photo'=>'required'
         ];
    }

Form data can be saved to database successfully if inputs are filled in completely.
But, when they are not filled in completely,or filled in nothing,
json message is shown in Chrome debugger's Preview and Response tags, like this:

{
"title":["The title field is required."],
"content":["The content field is required."],
...
}

But, the message can not be shown in html.
And ,at this time,".alert-success" is shown.
I don't know where the problems are in my code.

I think my understanding to done() and fail() is not right.
done() and fail() mean that ajax request is done or failed,
but not validation successful or failed,
no matter validation of laravel is successful or failed,
ajax request is done,
so,
even though I don't complete the inputs,
div class="alert alert-success" always appears .

1

1 Answers

3
votes

You're getting the success message because done() is fired when a "good" response is received. While you're getting error messages, the actual response from the server is still a 200.

You'd want to check the data in done() to make sure it isn't an error. If title === "The title field is required.", you'd want to run the code that is currently in your fail().

.done(function (data) {
  if(data.title[0] == 'The title field is required.' ) {
    alert('Title is required');
  }
  else {
    $(".alert-success").prop("hidden", false);
  }
})
.fail(function (data) {
  alert('The server failed somewhere');
});

Obviously, you'd want to do something other than alerts, and you'd want to check both fields, but that's the gist of it.