Uni-Form XHTML Forms Custom Tags v2

Posted on June 2, 2008 at 12:39 AM in ColdFusion, Uni-Form Tag Library, jQuery

It's been almost six months now since I released v1 of the library, so I figured it was high time I make time to add some enhancements. Here's a quick overview of the new features:

  • Integrated dependencies
  • Integrated support for the following jQuery plugins
    • Date Picker
    • Time Entry
    • Input Masking
    • Validation
  • Path Configuration

Let's look at some of the new goodies in more detail...

Integrated Dependencies

After a few months of using the library myself, one of the things that started to annoy me was the fact that I had to add the following into all of my applications in order to use the library:

  1. <link href="/cfMgmt/common/UniForm/css/uni-form.css" type="text/css" rel="stylesheet" media="all" />
  2. <link href="/cfMgmt/common/UniForm/css/uni-form-styles.css" type="text/css" rel="stylesheet" media="all" />
  3. <!--[if lte ie 6]>
  4. <style type="text/css" media="screen">.uniForm,.uniForm fieldset,.uniForm .ctrlHolder,.uniForm .formHint{ /* Trigger hasLayout*/zoom:1;}</style>
  5. <![endif]-->
  6. <InvalidTag src="/cfMgmt/common/UniForm/js/uni-form.jquery.js" type="text/javascript"></script>

I originally "fixed" this by using a <cfinclude />. While this worked okay, it was still kinda annoying to me, as I did not want to include the requirements on every page load. With this release, you no longer have to worry about that nonsense, because the dependencies are loaded automagically when you call the library.

Integrated jQuery plugins: Date Picker

v2 has a brand new 'loadDateUI' argument on the form tag, which accepts a boolean. If your form needs a date picker in it, just provide this new argument and set it to true.

  1. <uform:form action="action.cfm"
  2. id="myForm"
  3. loadDateUI="true">

Integrated jQuery plugins: Time Entry

Need a time entry field? Just use the new 'loadTimeUI' argument...

  1. <uform:form action="action.cfm"
  2. id="myForm"
  3. loadTimeUI="true">

Integrated jQuery plugins: Input Masking

"What about input masking?" you ask. You guessed it; just supply the 'loadMaskUI' argument...

  1. <uform:form action="action.cfm"
  2. id="myForm"
  3. loadMaskUI="true">

Integrated jQuery plugins: Validation

What good is a form without validation, right? Not much, to be sure. v2 utilizes jQuery's form validation plugin, which is integrated by setting the 'loadValidation' argument to true...

  1. <uform:form action="action.cfm"
  2. id="myForm"
  3. loadValidation="true">

... along with the new 'validation' argument for the field tag.

  1. <uform:field label="First Name"
  2. name="contactFirstName"
  3. isRequired="true"
  4. type="text"
  5. validation="required" />

One of the really bad-ass things about this plugin is that you can do basic client-side validation by simply adding a class to the field, such as 'required'. The plugin will check to make sure that field was filled out, and displays an error message if it isn't. Just supply validation="required" as shown above, and you're done. No JavaScript to write. Nothing. Just add it to your CF and stick a fork in it.

For those of you who like to take advantage of the more advanced features of the validation plugin, you should be able to continue to do so by utilizing this same argument. However, I must admit that I have not done any advanced testing with it as of yet, so if you run into any difficulties with that, please feel free to contact me and hopefully we can work together to iron it out.

Path Configuration

To load all of the various dependencies, the library uses convention to locate the required files. Should your application's directory structure require you to use paths other than the defaults (same directory structure as the download), you can utilize the form tag's new 'config' argument to supply the correct paths.

  1. <uform:form action="action.cfm"
  2. id="myForm"
  3. config="#myConfigStruct#">

As you can see, the config argument accepts a structure. Valid keys are:

  • renderer: path to the error message renderer
  • uniformCSS: path to the uni-form.css file
  • uniformJS: path to the jquery.uni-form.js file
  • validationJS: path to the jquery.validate.js file
  • dateCSS: path to the ui.datepicker.css file
  • dateJS: path to the ui.datepicker.js file
  • timeCSS: path to the jquery.timeentry.css file
  • timeJS: path to the jquery.timeentry.js file
  • maskJS: path to the jquery.maskedinput.js file

IMPORTANT NOTE #1!

Some of the JavaScript files have had modifications made to them in order to integrate with the Uni-Form markup. Changing the files will break things, so I would recommend changing only the path to them!

IMPORTANT NOTE #2!

For page load speed, the packed versions of the various JavaScript files are used. If you get really, really bored and decide to dig into them to see what changes I made, good luck. ;-)

IMPORTANT NOTE #3!

ALL of the new 'load{Dependency}' arguments default to FALSE. If you're not using a particular plugin for your form, no need to supply the argument. The scripts/CSS will *not* be loaded.

IMPORTANT NOTE #4!

It is assumed that you use jQuery for more than just your forms, and therefore already have it loaded by default. If, however, you don't, I decided at the last minute to include an argument to load it automatically with the form...

  1. <uform:form action="action.cfm"
  2. id="myForm"
  3. loadjQuery="true">

If you're not using jQuery elsewhere in your application, what the hell is wrong with you??!!??!!

:-)

Oh yeah, and if you decide to alter the path to jQuery itself, you can supply the 'jQuery' key in the config struct.

Summing it Up

Wanna see it in action?

Thanks to Dan Wilson for his contributions, and to everyone else out there that has had kind words for the library. You guys (and gals) all make it fun to release code. :-)

Update

Please see the 2.1 release for the download.

Comments
(Comment Moderation is enabled. Your comment will not appear until approved.)

On 6/2/08 at 6:34 AM, Tom K said:

Thanks for the update for this - Have been using v1 for a while now;
One of the first things I did was put the JS on cfhtmlhead on the form tag :)

i'm still trying to work out how to make a dropdown filled from a query though :(

On 6/2/08 at 7:32 AM, Sebastiaan said:

Hi, in the demo the date of birth and time of birth don't seem to be working for Opera (9.27 nor 9.5beta2). For the date of birth I get two - 2 - dateobjects on top of eachtother of which only the "ugly" one is usable. The bottom one (the nicely formatted one with colours and stuff) doens't work. For the date of birth the up/down/left/right arrows don't work at all.

On 6/2/08 at 2:02 PM, Matt Quackenbush said:

@ Sebastiaan - I have no idea what is happening there, as I made no changes to the DatePicker and TimeEntry plugins. I can only guess that there must be some sort of conflict between them and the Uni-Form markup when it comes to Opera. I'm not making an attempt to start a browser war here, but since less than 1.5% of users world-wide use Opera, and in my applications far less than 0.5% are Opera users, I must admit that that doesn't concern me enough to spend time on. If you (or anyone else) knows what the conflict(s) might be, I'd be happy to add your fix to the code provided it does not break anything in the commonly used browsers.

On 6/2/08 at 2:07 PM, Matt Quackenbush said:

@ Tom K - I'm not sure exactly what you mean, but if I'm understanding correctly, you'd just do something like so...

<uform:field label="My Label" name="fieldname" isRequired="true" type="select">
<cfloop query="myQuery">
   <uform:option display="#myQuery.myDisplayField[currentRow]#"
         value="#myQuery.myValueField[currentRow]#"
         isSelected="#myQuery.myValueField[currentRow] EQ form.fieldname#" />
</cfloop>
</uform:field>

On 6/2/08 at 6:05 PM, Jonathan van Zuijlekom said:

@Sebastiaan. When I click the Date of Birth field I get 2 date pickers, with the ugly one on top. Both work fine (even the left, right, up and down arrows). When I click the text Select Date next to the field I only nicely formated one, the slide-out animation is even smoother than with FF3. This is with the latest 9.5 build.

On 6/3/08 at 5:59 AM, Tom K said:

@ Matt
- Thanks - I didn't really think that I could do a conditional statement in this syntax:
ischecked="#form.ispublic EQ 1#" etc..

That solves a lot of my "hacking"!

On 6/4/08 at 6:38 PM, Dan said:

Is there any way to link 2 fields together with your tag? I have seen jQuery examples that use rules: { field2: { required: "#field1:checked" } } to make a second field required if the first field, a checkbox, is checked.

Also, is there a way to generate a multiple select box?

On 6/4/08 at 6:57 PM, Matt Quackenbush said:

@ Dan - As I stated in the post, I have not done any complex validation with jQuery's plugin, so I don't know for sure the answer to that question. Have you tried passing such rules into the 'validation' argument?

Multiple select is not currently supported as-is. I have added it to the feature requests for the next round of updates. :-)

On 6/4/08 at 7:27 PM, Dan said:

I tried the following combinations in the validate attribute for the Email Address field with no success.

##newsletter:checked
##newsletter-1:checked
$('newsletter').checked
$('newsletter-1').checked

The newsletter checkbox and email field combination are common on our site and we also are hoping to make a state/province dropdown required if the user chooses USA, otherwise if they choose any other country a "Other State/Province" text box magically appears and the state/province dropdown disappears.

You can check out an example at http://www.akextremeadventures.com/make_reservatio.... If you choose USA, Canada or Australia you then must choose from the state/province dropdown. Otherwise you get a text box. Of course, these forms took a lot of time to design and write the JS code, which is why I'm looking into your Uni-Form tag.

Here is the code just in case I did something dumb.

<div class="formContainer">
   <!--- build the form --->
   <uform:form action="action.cfm"
            id="myForm"
            submitValue="Send"
            showCancel="false"
            loadValidation="true"
            loadjQuery="true">
      <uform:fieldset legend="Your Info">
         <uform:field label="Name"
                     name="name"
                     isRequired="true"
                     type="text"
                     validation="required" />
                     
         <uform:field label="Newsletter Sign Up" isRequired="true" validation="required" name="newsletter" type="checkboxgroup">
            <uform:checkbox label="Yes I want to sign up for the newsletter" value="email" />
         </uform:field>
         
         <uform:field label="Email Address"
                     name="email"
                     isRequired="true"
                     type="text"
                     validation="$('newsletter-1').checked email" />
      </uform:fieldset>
   </uform:form>
</div>

Thanks,
Dan

On 6/4/08 at 7:43 PM, Matt Quackenbush said:

@ Dan - First off, no, you didn't do anything "dumb". :-)

It appears that I need to add a couple more things to the validation support in order to handle rules. As-is it will handle only the simple validations that are built-in to the plugin. It will be a little bit before I can take a good look at it, but I *think* it should be something I can bang out pretty quickly once I get a second to look into it. Hopefully I'll be able to do so in the next week or so.

In the meantime, you (or anyone else) should be able to write your rules externally (in a &lt;script&gt; block as you normally would), and also externally load the validation script that comes with the download. This should still allow full integration with the Uni-Form markup, with minimal extra code.

On 6/4/08 at 7:47 PM, Dan said:

Thanks I'll look into it. I'm new to jQuery so I'll have to play around with it a little.

Thanks again for the prompt response and cool new tool.

Dan

On 6/5/08 at 5:05 PM, Dan said:

I did figure out how to get this to work today. It took me longer to find the documentation than it did to correct my code. The only change I made to the code I posted earlier was to remove the isRequired and validation attributes from the email field. Then I added a script tag with the following code. This makes the email field required and it validates the field as an email address:

window.onload = function() {
   $("#contactEmail").rules("add", {
      required: "#newsletter-1:checked",
      email: true
   });
}

On 6/5/08 at 5:11 PM, Matt Quackenbush said:

@ Dan - Awesome! Thanks for posting the update. Just want to point out a couple of things...

1) try this for your function...

$(document).ready(function() {
$("#contactEmail").rules("add", {
required: "#newsletter-1:checked",
email: true
});
});

2) the isRequired argument on the tag should have zero affect on your validation routines. All it does (if set to true) is place the * next to the field, denoting it as being required.

On 6/5/08 at 6:30 PM, Dan said:

Yep, that works. I had to move the script block below the uform tags for now because I am letting your custom tag load jQuery.

On 6/10/08 at 9:28 PM, Jim Priest said:

I'm making heavy use of Jorn's validation plugin on a project. I'm curious with your tag - if I indicate a field is 'required' and disable JavaScript - does it fall back and use cfinput and do server side validation? That's been the big pain so far - writing the validations twice. One of these days I'll find time to mess around with Jaxer...

On 6/11/08 at 4:00 PM, Matt Quackenbush said:

@ Jim - No sir, the tags do not use cfinput. At this time server-side validation is not integrated with the tag library. However, there is a rumor floating around that an enhancement is in the works that would do just that.

On 6/12/08 at 11:45 AM, Matt MacDougall said:

Thanks for sharing this code. Just wanted to point out that the cfMgmt/common/images/icons directory is in subversion. When i tried to commit this to my local repository that bombed out. Removing the .svn directory in the icons directory allowed me to commit everything.

-Matt

On 6/12/08 at 2:55 PM, Matt Quackenbush said:

@ Matt - Thanks for pointing that out. I have removed it from the download, so it should be good to go now. :-)

On 2/3/09 at 12:11 PM, George said:

Hi Matt, I am plugging away with your library. I am trying to find a solution which will work inside your library to allow me to do 2 related selects? I looked at the cutom tag that Neil Weiss did called TwoSelectsRelated. Have you or any of your readers found a solution for 2 related selects which can work inside of cfuniform?
I am not getting any errors. I am getting four select boxes when I was only expecting 2 and when I select the first box the on change event never fires to load the second box.

On 2/3/09 at 8:11 PM, Matt Quackenbush said:

@ George - I have successfully used the jQuery selectchain plugin (link below) to handle multiple selects, and it has worked nicely. Here's a brief example.

<script>
// load cities based upon the state
$(function () {
   var state = $('#state');
   var city = $('#city');
   
   state.selectChain({
      target: city,
      url: '<cfoutput>#xit.loadCitiesByState#</cfoutput>',
      type: 'post',
      key: 'city',
      selectedValue: '<cfoutput>#address.getCity()#</cfoutput>',
      data: { ajax: true, anotherval: "anotherAction" }
   }).trigger('change');
});
</script>

<uform:field label="State" name="state" type="select" isRequired="yes">
   <uform:states-us fieldName="state" struct="#event.getCollection()#" defaultState="#address.getState()#" />
</uform:field>
<uform:field label="City" name="city" type="select" isRequired="yes">
   <option value="">-- Select State First --</option>
</uform:field>

Plugin Link: http://remysharp.com/2007/09/18/auto-populate-mult...

On 2/4/09 at 8:53 AM, George said:

Hi Matt, Thanks for this code. I have 2 questions. First, what is this parameter doing in the javascript call? url: cfoutput>#xit.loadCitiesByState#cfoutput?
Why did you use this in the first select uform:states-us? Was it because this field type was setup to take a struct as a parameter? And finally, what is going on with
data: ajax: true, anotherval: anotherAction

On 2/4/09 at 4:31 PM, Matt Quackenbush said:

@ George - The url attribute tells the javascript where to go and fetch the data from. The data attribute provides additional data to the controller (or the *.cfm page that is executing the request). I was just showing an example of passing a true|false (ajax: true) and a simple string value (anotherval: "anotherAction").

I'm not sure what you're asking about with the uform:states-us question.
CodeBassRadio

Latest Articles

Eventually something really brilliant and witty will appear right here.

Calendar

February 2020
S M T W T F S
« Jan  
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29

Subscribe

Enter a valid email address.

The Obligatory Wish List