I have the following markup for my input fields:

<!-- language: lang-html -->
<div class="required">
    <label for="Name">Name <em>*</em></label>		    
	<div class="input large">
        @Html.TextBoxFor(m => m.Name)
        @Html.ValidationMessageFor(m => m.Name)
    </div>
</div>

Using the jquery validation plugin if an error occurs then it will add a span below the input and also apply a class to the input itself so that the error can be styled. What I also want to do is add a class to the parent div with a class of required. So for example if an error happens it will be <div class="required error"> and then when fixed <div class="required valid"> in relation to the classes that are applied to the field and removal of the error span.

How would I do this? I've looked at the documentation site but haven't seen anything to do with adding a class to a parent div.

I've though about doing something like:

<!-- language: lang-js -->
if ($('input').hasClass('valid')) {
    $(this).parents('div.required').addClass('valid');

} else if ($('input').hasClass('input-validation-error')) {
    $(this).parents('div.required').addClass('error');
}

but how can I run it sequence with the validation? Like when an error takes place or a field becomes valid.

Access Validator Settings

The first order of business is to modify the settings object on your form's validator. You can do this in any of the following ways:

  1. Before the form is loaded for all forms by calling jQuery.validator.setDefaults()
  2. When initializing the form by passing in options on .validate([options])
  3. After initialization by locating the validator object on the form with $("form").data("validator").settings

Since you're using MVC, option #2 is out of the question since unobtrusive-validation will automatically initialize the form. So let's use option 3 going forward - the goal here is just to be able to customize the settings on the form.

Override Default Behavior

The default methods we'll want to modify are highlight and unhighlight which will highlight invalid fields or revert changes made by the highlight option, respectively. Here's their default behavior according to the source code:

<!-- language: lang-js -->
highlight: function( element, errorClass, validClass ) {
	if ( element.type === "radio" ) {
		this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
	} else {
		$( element ).addClass( errorClass ).removeClass( validClass );
	}
},
unhighlight: function( element, errorClass, validClass ) {
	if ( element.type === "radio" ) {
		this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
	} else {
		$( element ).removeClass( errorClass ).addClass( validClass );
	}
}

So you have a couple options here as well.

  1. Completely replace those functions and write them on your own
  2. Wrap those functions and call them like normal but add your own custom code before or after.

Option 1 - Replace Wholesale

This route is pretty easy. Just write whatever you want in there. Maybe seed from the source code, maybe do your own thing.

<!-- language: lang-js -->
var valSettings = $("form").data("validator").settings
valSettings.highlight = function(element, errorClass, validClass) { ... }
valSettings.unhighlight = function(element, errorClass, validClass) { ... }

Option 2 - Wrap Functions

This is less intrusive so probably preferable in most cases.

Since ultimately you will be replacing the value of valSettings.highlight, you'll need access to a clean pristine version of the original function. You can save your own or grab one off the global defaults

// original highlight function
var highlightOriginal = $("form").data("validator").settings.highlight;
var highlightDefaults = $.validator.defaults.highlight

In terms of wrapping JavaScript functions, there are a couple examples here, here, and here). Here's a parsed down example from one of those, that will help bind this context across function calls, preserve the arity of the arguments being passed, and persist the return value:

<!-- language: lang-js -->
function wrap(functionToWrap, beforeFunction) {
    return function () {
        var args = Array.prototype.slice.call(arguments),
        beforeFunction.apply(this, args);
        return functionToWrap.apply(this, args);
    };
};
<!-- language: lang-js -->

Then you'll also have to quickly define whatever additional behavior you want to fire whenever the call is made. In this case, let's find the closest parent div to the element and update it's classes like this:

function highlightDecorator(element, errorClass, validClass) {
    $(element).closest("div").addClass(errorClass).removeClass(validClass);
}

Wrapping It All Up <sup>(see what I did there)</sup>

<!-- language: lang-js -->
$(function () {
  var valSettings = $("form").data("validator").settings
  valSettings.highlight = wrap($.validator.defaults.highlight, highlightDecorator)
  valSettings.unhighlight = wrap($.validator.defaults.unhighlight, unhighlightDecorator)
});

function wrap(functionToWrap, beforeFunction) {
  return function () {
    var args = Array.prototype.slice.call(arguments);
    beforeFunction.apply(this, args);
    return functionToWrap.apply(this, args);
  };
};

function highlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(errorClass).removeClass(validClass);
}
function unhighlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(validClass).removeClass(errorClass);
}

So when we combine all of the above functions, it should look something like this:

Working Demo in Stack Snippets and jsFiddle

<!-- begin snippet: js hide: true console: true babel: false --> <!-- language: lang-js -->
$(function () {
  var valSettings = $("form").data("validator").settings
	valSettings.highlight = wrap($.validator.defaults.highlight, highlightDecorator)
  valSettings.unhighlight = wrap($.validator.defaults.unhighlight, unhighlightDecorator)
});

function wrap(functionToWrap, beforeFunction) {
  return function () {
    var args = Array.prototype.slice.call(arguments);
    beforeFunction.apply(this, args);
    return functionToWrap.apply(this, args);
  };
};

function highlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(errorClass).removeClass(validClass);
}
function unhighlightDecorator(element, errorClass, validClass) {
  $(element).closest("div").addClass(validClass).removeClass(errorClass);
}
<!-- language: lang-css -->
input.input-validation-error  {
  border: solid 1px red;
}
.input-validation-error label {
  color: red;
}
<!-- language: lang-html -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.16.0/jquery.validate.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js"></script>
    
<form action="/Person" method="post">
  
  <div class="required">
    <label for="Name">Name <em>*</em></label>           
    <input id="Name" name="Name" type="text" value="" 
           data-val="true" data-val-required="The Name field is required."/>
    <span class="field-validation-valid" 
          data-valmsg-for="Name" data-valmsg-replace="true"></span>
  </div>
  
  <input type="submit" value="Save" />
  
</form>
<!-- end snippet -->