3 min read

Using JQuery with Visualforce Pages

Lately I have been working to improve our user interfaces for areas of the application that we have customized heavily, most of which is modeled after the standard Salesforce CRM UI and works great.

However, there were a few features that I wanted to fully customize or provide better real-time interaction. I found that using Action Functions, Action Regions, and Action Status to be great for working with the data model but not great for responsive UI actions like a select all feature or even dependent UI components because they require the user to wait, needlessly, for the viewstate to be posted back and forth.

So I started using javascript to support client-side user interaction and quickly ran into issues with cross-browser compatibility. So that resulted in me reaching out to my favorite javascript library jQuery. I learned a couple of things quickly about using JQuery along side visualforce pages.

The first major hurdle was making sure that JQuery didn't interfere with any javascript libraries that Salesforce has implemented. Using firebug I was able to identify that they use extJS, what I believe to be prototype JS, and collection of functions specific to working with the Salesforce data model and UI. This was fairly simple to overcome by making sure that my scripts implemented the JQuery.noConflict() statement and to avoid using the "$" for the JQuery syntax.

Here is what that looks like:

jQuery.noConflict();

jQuery(document).ready( function() {
    jQuery("#someInputId").focus();
} );

The second thing that I had to overcome was interacting with apex elements that were rendered by Visualforce. This was an issue mainly because the Id of an apex element is generated using a namespace that includes the page id, form id, and then any parent components such as page blocks or output panels.

You can access the id of one these elements by using the $Component formula syntax but unless your script is right under the component (which it shouldn't be, ideally it would be at the end of the page) you have to type out the full namespace

For example:

{!$Component.pageId:formId:pageBlockId:myComponentId}

It is a bit tedious and unless your content changes very often you could just use firebug or some other tool to inspect the html and grab the id text. I often do this when I have a lot of nested components and I am not sure what the namespace will ultimately look like.

It is important to note at this point that even if you don't specify an id for an apex component Visualforce will assign an id to your component. So it is my recommendation to get in the habit of putting ids on elements that you plan to interact with or for key elements such as page, form, page block, or output panels to name a few.

So once you have a good handle on what your page will look like it is time to start adding some javascript to your pages. You have a couple of options at this point. You can imbed your javascript on the page or you can choose to add it as a static resource. What I typically do is write the javascript on the page so I can quickly make changes and debug. Once I feel confident enough in the script I will then replace it with a static resource.

The exception to this is if I only have a couple of lines of script then I will just leave it on that page. For instance if I just need to set focus on an element or set something trivial when the page loads then it doesn't seem worth it to put all of that in a separate file.

Adding the static resources to the page is very simple and can be done with a couple of tags. As a best practice I put the scripts at the bottom of that page, which is a common web development practice done for performance reasons. There is an article on Yahoo that does a pretty good job at summarizing the benefits.

Here is a sample:

Note: The sample code below has a bug. Continue reading to find out more

jQuery.noConflict();

jQuery(document).ready( function() {
    jQuery("#{!$Component.myPage:myForm:myBlock:inputAccountIndustry}").focus();
} );

As illustrated in the sample above the jQuery library is loaded using an apex include script tag and using the $Resource formula expression to get the url for the resource. This is then followed by the script that sets focus on the input element for the account industry field, however when the page loads something is wrong; the industry field is not in focus. So what happened? Well it turns out the jQuery selectors do not like the namespace convention that Visualforce utilizes and so it wasn't able to select the element and set focus.

But don't give up yet, there is a way around this and it is to grab the element using the document.getElementId method and pass the result to jQuery like so:

jQuery.noConflict();

jQuery(document).ready( function() {
    var myElement = document.getElementById("{!$Component.pageId:formId:myComponentId}");
    jQuery(myElement).focus();
} );

So using the syntax above your element is selected and the element object is then passed to jQuery which is now able to extend the element as needed.

So there you have a couple of lessons learned by yours truly in implementing jQuery with Visualforce. Feel free to comment on your experiences or if you have any questions I would be happy to expand on the subject more.