waytogo
waytogo

Reputation: 57

How to display the validation error in blade using ajax?

How to display the error message in blade using ajax? My code working well, the validation message appear in inspect element, but not in my blade form. I'm using Laravel 8.

Controller

    public function store(StudentRequest $request)
    {
        $request->validate();
        $input = $request->all();

        Student::updateOrCreate(['id' => $request->id], $input);
        return response()->json(['success' => 'Added new student']);
    }

I'm using form request to handle the validation:

Request

    public function rules()
    {
        return [
            'name'  => 'required',
            'email' => 'required|email',
        ];
    }

And this is my blade. I used printErrorMsg() to display all the validation error above the form, but it doesn't work and showed nothing.

Blade

    <form id="studentForm" name="studentForm" class="form-horizontal" enctype="multipart/form-data" method="POST">
        {{ csrf_field() }}

        <div class="alert alert-danger print-error-msg" style="display:none">
            <ul></ul>
        </div>

        <input type="hidden" name="id" id="id">
        <div class="form-group">
            <label for="name" class="col-sm-2 control-label">Name</label>
            <div class="col-sm-12">
                <input type="text" class="form-control" id="name" name="name" placeholder="Enter Name" value="">
            </div>
        </div>

        <div class="form-group">
            <label for="email" class="col-sm-2 control-label">Email</label>
            <div class="col-sm-12">
                <input type="text" class="form-control" id="email" name="email" placeholder="Enter Email" value="">
            </div>
        </div>

        <div class="col-sm-offset-2 col-sm-10">
            <button type="submit" class="btn btn-primary" id="saveBtn" value="create">Save changes</button>
        </div>

    </form>
    @endsection

    @push('scripts')
    <script type="text/javascript">
    $(function() {
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

        $('#createNewStudent').click(function() {
            $('#saveBtn').val("create-student");
            $('#id').val('');
            $('#studentForm').trigger("reset");
            $('#modelHeading').html("Create New Student");
            $('#ajaxModel').modal('show');
        });

        $('#studentForm').submit(function(e) {
            e.preventDefault();
            let formData = new FormData(this);

            $.ajax({
                data: formData,
                url: "{{ route('students.store') }}",
                type: "POST",
                dataType: 'json',
                contentType: false,
                cache: false,
                processData: false,
                success: function(data) {
                    if($.isEmptyObject(data.error)){
                        alert(data.success);
                        $('#studentForm').trigger("reset");
                        $('#ajaxModel').modal('hide');
                        table.draw();
                    }else{
                        printErrorMsg(data.error);
                    }
                },
            });
        });

        function printErrorMsg (msg) {
            $(".print-error-msg").find("ul").html('');
            $(".print-error-msg").css('display','block');
            $.each( msg, function( key, value ) {
                $(".print-error-msg").find("ul").append('<li>'+value+'</li>');
            });
        }
    });
    </script>

    @endpush

Edited:

I solved this by linktoahref's answer and Sachin Kumar's comment. I remove printErrorMsg() function in my blade and change it to spans element for each field with id and using responseText to return the js strings. So, here's the edited code:

Blade:

<div class="form-group">
 <label for="email" class="col-sm-2 control-label">Email</label>
 <div class="col-sm-12">
  <input type="text" class="form-control" id="email" name="email"/>
  <small id="email_error" class="form-text text-danger"></small>
 </div>
</div>

$('#studentForm').submit(function(e) {
    e.preventDefault();
    $('#name_error').text('');
    $('#email_error').text('');
    let formData = new FormData(this);
    $.ajax({
        data: formData,
        url: "{{ route('students.store') }}",
        type: "POST",
        dataType: 'json',
        contentType: false,
        cache: false,
        processData: false,
        success: function(data) {
            if (data.status == true) {
                alert('Success!');
                $('#studentForm').trigger("reset");
                $('#ajaxModel').modal('hide');
                table.draw();
            }
        },
        error: function(reject) {
            var response = $.parseJSON(reject.responseText);
            $.each(response.errors, function(key, val) {
                $("#" + key + "_error").text(val[0]);
            })
        }
    });
});

Thank you

Upvotes: 5

Views: 5938

Answers (1)

linktoahref
linktoahref

Reputation: 7972

Extending Sachin Kumar's comment, the validation errors returned from Laravel would have an http response code of 422 and would be available in the error callback of AJAX.

So you may add additional spans in your html to accommodate the errors and hide it initially and display it on validation errors.

<div class="form-group">
    <label for="name" class="col-sm-2 control-label">Name</label>
    <div class="col-sm-12">
        <input type="text" 
            class="form-control"
            id="name"
            name="name"
            placeholder="Enter Name" value="">
        <span class="error text-danger d-none"></span>
    </div>
</div>

<div class="form-group">
    <label for="email" class="col-sm-2 control-label">Email</label>
    <div class="col-sm-12">
        <input type="text" 
            class="form-control"
            id="email"
            name="email"
            placeholder="Enter Email" value="">
        <span class="error text-danger d-none"></span>
    </div>
</div>

And process the validation errors in the error callback as follows:

$.ajax({
    ...
    error: function (err) {
        $.each(err.responseJSON.errors, function (key, value) {
            $("#" + key).next().html(value[0]);
            $("#" + key).next().removeClass('d-none');
        });
    },
    ...
});

Upvotes: 4

Related Questions