\\//,
You all know I'm a freelancer working for different clients, and if you didn't know, you know now! One of the clients I work for I help out with the development of their application.
Now the particular client's site is actually a data input site. Where the data can range from normal text to full files containing text to be analyzed. We actually got the generation of forms working a while ago, and the client added jquery validation to it. Which worked nicely and everyone was happy. Until recently he came up with this:
Is it possible to generate our forms completely with auto hide/show for conditional inputs?
I answered that it was possible but would be a bit of work to get everything working (the rules are subject also to the conditional).
So this is how I solved it:
- The serverside generates a html page with all inputs but the "children" (read conditionals with their rules) are given the hidden class. (Using bootstrap yes)
- The serverside generates a javascript variable that contains the validation rules per child input (id is the key)
- The div containing the child's input and label has 2 attributes : parent_input and child_name (this because the 2 keys are the only way to find the correct rule)
- created a java function that will process the rules upon change triggered on the parent
- created a java function that will show/hide the input when the previous function asks it.
The cool thing is that with jquery validation you can easily add and remove rules. And that is something you mostly do not do (if you don't have a data input site with conditionals).
So here is the code how to do that:
// the {{ child_rules }} comes from the serverside, this part will pass through template engine./* rules are setup like this:var child_rules = { 'parent_name' : { 'child_name: { 'rules': { 'required': true, 'messages': { 'required': "this field is a required field" } }, 'display_rules': { } } }}*/varchild_rules={{child_rules}};functiondisplay_child(par,child){varelem=$("div[child_attribute='"+child+"'][parent_attribute='"+par+"']");if(elem.hasClass('hidden')){elem.removeClass('hidden')if(elem.children('select').length>0)elem.children('select').focus().rules('add',child_rules[par][child]['rules']);elseelem.children('input').focus().rules('add',child_rules[par][child]['rules']);}}functionhide_child(par,child){varelem=$("div[child_attribute='"+child+"'][parent_attribute='"+par+"']");if(!elem.hasClass('hidden')){elem.addClass('hidden');if(elem.children('select').length>0)elem.children('select').rules('remove');elseelem.children('input').rules('remove');}}functionprocess_child_rules(par){$('#id_'+par).blur(function(){for(varkeyinchild_rules[par]){/* key contains now a child_attribute each child_attribute has it's rules, it's messages and it's display_rule. if rule matches the parents value, then run the display_child function else hide_child. The function to check whether the rule matches is not given as it's not important can be any function as long as it returns a bool. */if(function_to_check_whether_rule_matches()){// evaluated to truedisplay_child(par,key);}else{hide_child(par,key);}}});}$(document).ready(function(){$(".form-horizontal").validate(// Initial validation of all the default parent inputs{{validate_options}});for(varkeyinchild_rules){// Process the rules if any!process_child_rules(key);}});
Small remark: We only have input(text) and selects. No radiogroups textarea's.
I never ran the code that I pasted here throught jslint etc, so no need in complaining about codestyle or other issues :P.
Be aware that this is an adaptation of our working code just to show the possibilities.
LLAP
Jochen