Microsoft.jQuery.Unobtrusive.Validation version 3.2.0, errorPlacement and knockout templates–oh my

The problem:

Client-side validation (with jQuery validate + Microsoft’s jQuery Unobtrusive wiring things up via data attributes) was ignoring the markup I designated for errorPlacement (<div data-valmsg-for=”myCorrespondingInputToValidate”/>), and instead, was happily placing the generated error label right next to the input (which is the default jQuery validate behavior).  The resulting visual effect (using some bootstrap styling) was something like this:

screenshot

I was pretty sure this was working not long ago, but I had been shuffling things around so I figured I had probably jacked it up somewhere.  I compared my markup against a page that was not experiencing the visual oddity and the markup was similar.  What I did notice, however, was that page had it’s markup contained in the page, while mine was broken into numerous knockout templates.  Hm….that *is* a difference…so the digging begins….

We have numerous custom client modules for dealing with the intersection of jQuery, knockout and unobtrusive, so it took a bit of time to discover the root cause, but I’ll spare you that pain.  The bottom-line:  the newest version of the unobtrusive library made a subtle, yet-impactful change to the selectors they use when parsing the initial document. 

screenshot2

In my code, I have all my inputs broken into knockout templates, which get injected into the DOM after the point the unobtrusive module fires.  If you look at the source for jQuery validate, you’ll see that “he who calls validate first wins” with regard to settings, as they are essentially loaded one-time and re-used.  So, even if we called $jQval.unobtrusive.parse(document) again, it would be too late – the settings have already taken-hold.  This translated into a loss of the errorPlacement function which unobtrusive would normally wire up for us, if that call to validationInfo.attachValidation had occurred.  And that is why the default behavior of inserting a label after the validated form field occurred. 

Ok, yay, so now what?

On one hand, you could argue that this is potentially-flawed in the design – or at least could be exposed as some sort of option.  I could also see this being somewhat edge-case-ish in that literally *all* my markup with inputs is separated into separate knockout templates and that may be somewhat unusual I suppose.  So, while you could look into changing the unobtrusive library (via forking or something along those lines), I opted for a less-dangerous approach (we’ve already forked other libraries and this would be one less to keep track of): I met the requirement of at least one form field with data-val=”true”:

<form id=’myForm>

<!– This is here so jquery.validate.unobtrusive
      will set jquery validate’s settings –>
       <input type="hidden" data-val="true" disabled="disabled" />

Cheese?  Maybe.  Reasonably clear and effective?  Yeah.

Of course, many other options exist.