jQuery looping on fields after validation I have the following code:

$(":input, textarea, select").on('blur', function(ev) {

var data = $('#campaign-form').serialize();

$.ajax({
    url: "/campaign/validate",
    type: "POST",
    data: data,
    cache: false,
    dataType: 'json',
    success: function (data) {
        if (data) {

            /*Assign error classes*/
            $.each(data, function (field, message) {
                jQuery("#" + field).addClass('input-error');
                jQuery("#" + field + "-error").text(message);
            })
        }
    }
});


This code adds a class 'input-error' to fields which have an error (validated on the PHP side).

The issue is that if I fix the error, and send validation again, the input-error class is not removed. Also I need to add class input-valid to the correct fields.

I have tried a solution, but it does not look optimal (it does make the work though).

$(":input, textarea, select").on('blur', function(ev) {

var data = $('#campaign-form').serialize();

$.ajax({
    url: "/campaign/validate",
    type: "POST",
    data: data,
    cache: false,
    dataType: 'json',
    success: function (data) {
        if(data) {

            /*Remove classes for all fields in the form*/
            clearFields = $("#campaign-form :input.gg-field, #campaign-form textarea.gg-textarea, #campaign-form select.gfp-field").each(function(index) {
                var input = $(this);
                var fieldId = input.attr('id');
                jQuery("#"+fieldId).removeClass('input-valid');
                jQuery("#"+fieldId).removeClass('input-error');
                jQuery("#"+fieldId+"-error").text("");

            });

            /*Assign error classes*/
            $.each(data, function(field, message) {
                jQuery("#"+field).addClass('input-error');
                jQuery("#"+field+"-error").text(message);
            })

            /*To the other fields assign valid classes*/
            validFields = $("#campaign-form :input.gg-field, #campaign-form textarea.gg-textarea, #campaign-form select.gfp-field").not( ".input-error" ).each(
                function(index) {
                    var input = $(this);
                    var fieldId = input.attr('id');
                    jQuery("#"+fieldId).addClass('input-valid');
                    jQuery("#"+fieldId+"-error").text("");
                });

        }
    }
});


I would like to verify which fields are coming on the data JSON object in order to assign the error or valid class in that process, avoiding the need to loop through the fields again.

Data object example:

{ "title":"* The Campaign Title field is required.",
  "description":"* The Description field is required.",
  "campaign_category_id":"* The Campaign Category field is required."
}
Why not just iterate over the inputs, and if the values of the id attribute exists in data then add the error class and show the affiliated error message, otherwise add the valid class and clear the error message? 

When the DOM is ready, the input values can be stored in a variable:

$(function() { //DOM-ready
    //cache the inputs from the DOM so as to minimize DOM queries.
    const inputs = $(":input");


Note that texetarea, select were removed from the selector because the jQuery :input selector includes those.

Then inputs can be used for registering the blur callback:

inputs.on('blur', function(ev) {


And then in the success callback of the AJAX request, inputs can be used again with $.each():

success: function(data) {
    if (data) {
      $.each(inputs, function(index, input) {


Then to determine if the field is invalid, check if the id
 attribute exists as a property of data. jQuery(input).prop() can be used to get the id property. Then data.hasOwnProperty() can be used to determine if the id property is set on data.

const id = jQuery(input).prop('id');
if (data.hasOwnProperty(id)) {
  jQuery(input).addClass('input-error')
      .removeClass('input-valid'); //chain calls for efficiency
  jQuery("#" + id + "-error").text(data[id]);
}
else {
  jQuery(input).removeClass('input-error')
      .addClass('input-valid');
  jQuery("#" + id + "-error").text("");
}


For a demonstration of this, see this plunker. Note that the AJAX response is not dynamic.

Actually, that last block could be re-written to utilize jQuery's toggleClass() method.

let message = '';
if (data.hasOwnProperty(id)) {
    message = data[id];
}
jQuery(input).toggleClass('input-error', message !== '')
    .toggleClass('input-valid', message === '');
jQuery("#" + id + "-error").text(message);


See a demonstration of that in this plunker.