4

My form I am designing with MVC 4 has mutiple DIVS with many elements in each one. My objective is to open/close DIVS as the user completes the fields. However, I want to use the unobtrusive validation on each DIV, rather than the whole form. Is that possible without checking each element individually? Maybe using a DIV ID or something? I don't want to build this massive function to check each and every element in each DIV just so the user can move to the next DIV.

I am trying this and it is not working:

 var elems = [];
 var valid = true;
 ("#Contact").find('.text_input').each(function() {
    elems.push(this.id);
  }
  for (var i = 0; i<= elems.length; i++) {
       if ($("#" + elems[i]) != undefined) {
           $("#form1").validate().element("#" + elems[i]))
           if ($("#" + elems[i]).valid()) {
           }
           else {
             valid = false;
           }
        }
   }

but I keep getting an undefined error. The elements in the DIV that have the class text_input are the ones with validation required.

2
  • When would you validate the elements within a div? For example, when the last element in the div loses focus or when you click on a button to show the next div? Commented Sep 3, 2014 at 12:25
  • 1
    In this case, when the user clicks Next, which calls a function to hide the first div and show the second. But I want to check the elements in that first div before showing the second one? Does that make sense? Commented Sep 3, 2014 at 12:27

1 Answer 1

8

You can validate individual controls using Validator.element(element) - see documentation here, so you could use the following approach (you haven't posted the views html so can't write the actual code for you)

In the Next button click event

  1. Select all the the controls within the associated div - e.g. var controls = $(this).closest('div').find('input, textarea, select');
  2. In an $.each loop, call $("form").validate().element($(this));
  3. If necessary, test if valid with $(this).valid();
  4. If everything is valid, hide the current div and display the next

Edit (example added)

View

<div class="section">
  <h2>Section 1</h2>
  .... // Your inputs and validation
    @Html.LabelFor(m => m.SomeProperty)
    @Html.TextBoxFor(m => m.SomeProperty)
    @Html.ValidationMessageFor(m => m.SomeProperty)
  <div class="error"></div>
  <button type="button" class="next">Next</button>
</div>
<div class="section">
  <h2>Section 2</h2>
  .... // Your inputs and validation
  <div class="error"></div>
  <button type="button" class="next">Next</button>
</div>
<div class="section">
  <h2>Section 3</h2>
  .... // Your inputs and validation
  <div class="error"></div>
  <button type="submit" class="next">Submit</button> // submit button for last section
</div>

CSS

.section:not(:first-of-type) {
    display:none;
}

Script

$('button').click(function () {
  var container = $(this).closest('.section');
  var isValid = true;     
  $.each(container.find('input'), function () {
    $('form').validate().element($(this));
    if (!$(this).valid()) {
      isValid = false;
      return false;
    }
  });
  if (isValid) {
    container.next('.section').show().find('input').first().focus();
    container.hide();
  } else {
    container.find('.error').text('please complete');
  }
});
Sign up to request clarification or add additional context in comments.

5 Comments

check my edits and let me know why that doesn't work
There is no reason to put it into an array. After var controls = ... then $.each(controls, function(index, item) { $("#form1").validate().element($(this)); - or it might need to be ..element($(this)[0]); - not sure without testing
Could you possibly write out the function for me?
Its late - I'll have a look tommorow
@StephenMuecke, Great solution. Very simple and not much code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.