Home  >  

jQuery Example: Binding form fields

Author photo
AddThis Social Bookmark Button
A user on the cf-talk mailing list had an interesting question. He wanted to create a form with three fields: first name, last name, and profile name. The profile name should be automatically filled out based on the first name and last name values. So if I entered Darth Lohan as my name, the profile field should be set to: DarthLohan. However, he then had a little twist. If the user edits the profile field, the automatic updating of the profile field should stop. This part concerned me. I was relatively certain it would be easy to automatically set the profile field, what I wasn't sure about was how to disable the behavior when the user changed the field manually. I came up with the following solution that I think works nicely, but I'd love to get some feedback from others. Have a nicer solution? Please, share it!
<script src="jquery/jquery.js"></script>
<script>
$(document).ready(function() {
 
 	$("#firstName").keyup(setProfile)
 	$("#lastName").keyup(setProfile)
 	$("#profileName").keypress(disableMe)
 	
})

var doIt = true
function setProfile() {
 	if(doIt) $("#profileName").val($("#firstName").val() + $("#lastName").val())
}

function disableMe() { doIt=false }
</script>

first name <input type="text" name="First_name" id="firstName" ><br/>
last name <input type="text" name="Last_name" id="lastName" /><br/>
profile name<input type="text" name="Profile_name" id="profileName" />
So I like to code upwards. Don't ask me why. I guess because I like to lay out the UI first then add the JavaScript on top. Forgive me for walking through the code backwards. Starting at the bottom I've got my form with the three fields. Normally I'd wrap it with form tags, but it's just a demo so I'm OK with it as is. Up in the script block, take note first of the three event handlers. I monitor the keyup events for firstname and lastname. I monitor the keypress event for profileName. The event handlers for firstname and lastname do what you would expect - update the profileName field. You could modify it to add a _ between the two fields if you wanted a bit of separation. The profileName keypress event handler simply toggles the doIt variable to false. Did you notice that the setProfile function checks that value? This means that as soon as you hit a key in the profileName field, the setProfile function will no longer do anything. So this works, but isn't perfect. First off, it assumes that the keypress in the profile actually changed the value. In theory I could type X, then delete X. But I don't think most people would require that level of specificity. You can see a demo of this here. I was about to hit Save when I decided to do a quick Google search. As I imagined, there is a nicer way of doing this. jQuery supports a simple unbind call that removes event handlers. I modified the code to use this and it feels a bit cleaner to me:
<script>
$(document).ready(function() {
 
 	$("#firstName").keyup(setProfile)
 	$("#lastName").keyup(setProfile)
 	$("#profileName").keypress(disableMe)
 	
})

function setProfile() {
 	$("#profileName").val($("#firstName").val() + $("#lastName").val())
}

function disableMe() { 
 	$("#firstName").unbind("keyup")
 	$("#lastName").unbind("keyup")
}
</script>
Note now that setProfile doesn't have to check to see if it should run and disableMe simply removes the event listeners from the fields. Ok, so is there an even better way?

Read more from Raymond Camden. Raymond Camden's Atom feed cfjedimaster on Twitter

Comments

9 Comments

Todd Sharp said:

Makes sense to me. The only change I'd suggest is to have the profileName be a and just display it as read only. And, I assume the real requirement would be that the username should not change once it's set in the DB - so in reality wouldn't it make more sense to just add conditional logic to not even set up the listeners to call setProfile on page load (when a user would be editing their profile, not creating it)? Just my two cents.... If anything I'd call the disableMe() on form submit (or click of the 'save' button).

Todd Sharp said:

ooops - html stripped - should read <span>

Raymond Camden said:

Well, the requirement was to allow the user to edit the profile. If not, then yep, I'd use a span. That would be perfect.

Dan G. Switzer, II said:

Here's a pared down version of what you have. The key change is that I've combined the selectors to shorten the code and added a namespace to the bind handler--which allows you to specifically unbind a specific handler, otherwise all of your bound keyboard events would get unbound--which would cause problems if you have other similar bound events (such as for validation.)

$(document).ready(function(){

$("#firstName,#lastName").bind("keyup.setProfile", setProfile);
$("#profileName").bind("keypress.disableMe", disableMe);

});

function setProfile() {
$("#profileName").val($("#firstName").val() + $("#lastName").val())
}

function disableMe() {
$("#firstName,#lastName").unbind("keyup.setProfile");
}

You can reduce the code further to:
$(document).ready(function(){

function setProfile(){
$("#profileName").val($("#firstName").val() + $("#lastName").val())
}

$("#firstName,#lastName").bind("keyup.setProfile", setProfile);

$("#profileName").bind("keypress.disableMe", function (){
$("#firstName,#lastName").unbind("keyup.setProfile");
});

});

Raymond Camden said:

That is slick. Am I to understand that bind(A.X) means:

bind the event A, and use key X as a label

?

Dan G. Switzer, II said:

@Raymond:

Yes, jQuery allows you to provide a namespace for event binding--which allows you to easily remove specific named bindings; leaving the other bindings intact.

So, for example:

$("a").bind("click.window", function (){});

We've used a binding of "click.window". The first part "click" is the actual event handler to use. The remainding portion is the namespace for the event.

What's nice is if you have multiple events bound:

$("a")
.bind("click.window", func())
.bind("mouseenter", func())
.bind("mouseleave.window", func());

You can unbind all events by doing:
$("a").unbind(".window");

Raymond Camden said:

To be anal, doesn't your unbind only remove the 1st and 3rd bind?

Dan G. Switzer, II said:

Yeah, that was a typo--I missed the namespace in the mouseenter binding.

Raymond Camden said:

Thanks - I will probably use this for a blog entry next week. :)

Leave a comment


Tag Cloud

iPad

What's your take on the iPad? (Putting aside the Flash/iPad flame war)

Answer

Latest Features

Recommended for You

@InsideRIA on Twitter

Archives

  • Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.