VisualForce Component Ids & Javascript

I have retired this approach in favour of a much neater solution that can be found here.

Salesforce used in conjunction with JavaScript and Ajax can be pretty smashing. I’ve used a number of JavaScript libraries that make you want to high-five yourself when implemented. There can(and probably will) be some frustration while you bend a library and make it fit within the Salesforce framework, although Ron Hess has some pretty sweet examples for you to pore over.

One simple frustration I’ve come across is that of retrieving elements by Id. Salesforce has an intelligent scheme in place which ensures that HTML elements don’t have duplicate Ids and therefore conform to W3C standards. Consider the following VisualForce page

<apex:page id=”thePage”>

<apex:pageBlock id=”theBlock”>

<apex:outputText id=”theText”  …/>

</apex:pageBlock>

</apex:page>

The generated element Id for the outputText field would be ‘thePage:theBlock:theText’ and not simply ‘theText’. In terms of web-standard conformity this is great, but for the beginner combining JavaScript and VisualForce this can be a nightmare. Imagine you have an outputText field nested ten levels deep within the page. Were you to hardcode the Id of this element within your JavaScript you have to bear the following in mind,

  1. Salesforce give elements random Id values if you don’t assign them explicitly. To prevent this you have to assign an Id to each parent element.
  2. If you change the page tree structure that precedes said element, you have to change the Id referenced in your JavaScript.

Not the most fun you’ve had, and a lot of hard work if you ask me. Luckily there is a simple solution, and it’s easily maintained as well as flexible. All you have to do is assign the element value to a JavaScript variable just after it appears in the page(or at the same level within the page tree). The code would become

<apex:page id=”thePage”>

<apex:pageBlock id=”theBlock”>

<apex:outputText id=”theText”  …/>

<script> var theText = document.getElementById(“{!$Component.theText}”); </script>

</apex:pageBlock>

</apex:page>

Baddabing baddaboom! Now you can reference the JavaScript variable ‘theText’ from within you JavaScript code and be happy that all that nonsense about hardcoding the Id value is behind you.

80 thoughts on “VisualForce Component Ids & Javascript”

  1. So does it take anything special to get this to work? I can’t get it to return anything.

    For example, I have the following in my form and {!$Component.caseSubType} doesn’t seem to return anything.

    Reply
    • Nothing extra special is needed, the example I’ve given is a worked one. Perhaps you can post a bit more code to the discussion boards and PM me a link to the post? My username is wesnolte.

      Reply
  2. So does it take anything special to get this to work? I can’t get it to return anything.

    For example, I have the following in my form and {!$Component.caseSubType} doesn’t seem to return anything.

    Reply
    • Nothing extra special is needed, the example I’ve given is a worked one. Perhaps you can post a bit more code to the discussion boards and PM me a link to the post? My username is wesnolte.

      Reply
  3. Thank you for this but it does not seem to work for me. Here is the code i am using and the alert is not being displayed.

    var zip = document.getElementById(“{!$Component.zipcode}”);
    alert(‘zip:’+zip);

    Reply
  4. is your declaration of the variable ‘zip’ at the same level in the DOM tree as the visualforce element with Id ‘zipcode’? Note that ‘zipcode’ is also case-sensitive.

    Reply
    • Yes it is within the same pageBlocksection.

      var zip = document.getElementById(“{!$Component.zipcode}”);
      alert(‘zip:’+zip);

      Reply
  5. is your declaration of the variable ‘zip’ at the same level in the DOM tree as the visualforce element with Id ‘zipcode’? Note that ‘zipcode’ is also case-sensitive.

    Reply
    • Yes it is within the same pageBlocksection.

      var zip = document.getElementById(“{!$Component.zipcode}”);
      alert(‘zip:’+zip);

      Reply
    • Which is correct. You are returning the entire element, if you want the value you’ll need to use zip.text or zip.value (depend which type of element is rendered, but it seems to be a span-element).

      Reply
    • Which is correct. You are returning the entire element, if you want the value you’ll need to use zip.text or zip.value (depend which type of element is rendered, but it seems to be a span-element).

      Reply
  6. Which is correct. You are returning the entire element, if you want the value you’ll need to use zip.text or zip.value (depend which type of element is rendered, but it seems to be a span-element).

    Reply
  7. Hi,
    I have a problem while retrieving elements by id. I am able to retrieve one element and append to url and send it to next page. But while doing the same for second element , i am able to capture the value using getelement by id and can append it to URL too. But , i am unable to use the url appended second value in second page.

    Is there any limitation in VF or JS that only single element should be transmitted or anything?

    Reply
    • Nope, this is doable. If you post something to the discussion boards and tweet me (twitter.com/weesildotn) the url to the post I’ll check it out. Be sure to post the relevant code.

      Reply
  8. Hi,
    I have a problem while retrieving elements by id. I am able to retrieve one element and append to url and send it to next page. But while doing the same for second element , i am able to capture the value using getelement by id and can append it to URL too. But , i am unable to use the url appended second value in second page.

    Is there any limitation in VF or JS that only single element should be transmitted or anything?

    Reply
  9. Hello,

    I have a problem with my javascript and visualforce page concerning visualforce component Ids itself when the page is called using a URL parameter.
    Please see my post on http://pastebin.com/hSjBxXXi and if you could provide me with a solution or suggest a website for reference.

    Thanks in advance.

    Reply
      • Thanks for your prompt reply.Your solution works :D. In the part u modified, i wanted some explanation on

        I understood the variable declaration and its use. However, the placement of the variable declaration can be before (membersTable) or after (frmMembers) the id assignment in visualforce?

        Secondly the membersTable + ‘:’ means referencing ids from the membersTable to the appropriate component where the javascript function is called?

        Once again thanks a lot. Ur solution help us greatly.

        Reply
  10. Hello,

    I have a problem with my javascript and visualforce page concerning visualforce component Ids itself when the page is called using a URL parameter.
    Please see my post on http://pastebin.com/hSjBxXXi and if you could provide me with a solution or suggest a website for reference.

    Thanks in advance.

    Reply
      • Thanks for your prompt reply.Your solution works :D. In the part u modified, i wanted some explanation on

        I understood the variable declaration and its use. However, the placement of the variable declaration can be before (membersTable) or after (frmMembers) the id assignment in visualforce?

        Secondly the membersTable + ‘:’ means referencing ids from the membersTable to the appropriate component where the javascript function is called?

        Once again thanks a lot. Ur solution help us greatly.

        Reply
    • The JS variable declaration has to be at the same level in the DOM tree as the element it references. So it can be before or after as long as this rule applies.

      And for the second question (if I understand correctly), yes 🙂

      Reply
  11. Hello,

    I have a problem with my javascript and visualforce page concerning visualforce component Ids itself when the page is called using a URL parameter.
    Please see my post on http://pastebin.com/hSjBxXXi and if you could provide me with a solution or suggest a website for reference.

    Thanks in advance.

    Reply
    • The JS variable declaration has to be at the same level in the DOM tree as the element it references. So it can be before or after as long as this rule applies.

      And for the second question (if I understand correctly), yes 🙂

      Reply
  12. I can get this to work, BUT I am having one niche issue. Because Salesforce uses so many tables to render their pages, the scripts after a field in a pageBlockSection end up being in tables. In IE6, running a script in a table causes quirks. Namely, it makes Google Maps go awry (see http://blog.evandavey.com/2008/08/how-to-fix-problems-with-google-mapsinternet-explorer-grey-background-etc.html)

    I tried putting the scripts at the end of the page, but the $Component values were not filled in.

    Ideas other than not using pagBlockSections?

    Reply
  13. I can get this to work, BUT I am having one niche issue. Because Salesforce uses so many tables to render their pages, the scripts after a field in a pageBlockSection end up being in tables. In IE6, running a script in a table causes quirks. Namely, it makes Google Maps go awry (see http://blog.evandavey.com/2008/08/how-to-fix-problems-with-google-mapsinternet-explorer-grey-background-etc.html)

    I tried putting the scripts at the end of the page, but the $Component values were not filled in.

    Ideas other than not using pagBlockSections?

    Reply
    • As it turns out, that wasn’t my issue. I was running script at the bottom of the page, but modified it to run “onload” using an event listener and all is good.

      This was purely a Google Maps issue, so disregard.

      Reply
  14. The markup would be much simpler to just wrap the input with a span that has a certain id or class and your done. No inline javascript.

    Using jQuery, you could then just say:

    $el = $(‘input’, mySelector );

    …and you’re done.

    Reply
  15. The markup would be much simpler to just wrap the input with a span that has a certain id or class and your done. No inline javascript.

    Using jQuery, you could then just say:

    $el = $(‘input’, mySelector );

    …and you’re done.

    Reply
  16. The markup would be much simpler to just wrap the input with a span that has a certain id or class and your done. No inline javascript.

    Using jQuery, you could then just say:

    $el = $(‘input’, mySelector );

    …and you’re done.

    Reply

Leave a Comment