The Silver Lining

Lessons & Learnings from a salesforce certified technical architect.

VisualForce Component Ids & Javascript

with 33 comments

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.

Advertisements

Written by Wes

June 17, 2009 at 6:00 pm

33 Responses

Subscribe to comments with RSS.

  1. this is good, thanks!!

    mallika

    July 8, 2009 at 3:59 pm

  2. This worked great. May I ask some assistance, please.

    … some parts missing …

    Thanks, Brian

    Brian

    July 14, 2009 at 12:30 pm

  3. 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.

    Scott Hemmeter

    August 19, 2009 at 8:12 am

    • 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.

      Wes

      August 19, 2009 at 9:17 am

  4. […] preparation you may want to read this article on VisualForce and JavaScript, as well as this writeup on using VisualForce Ids with jQuery. Both will pad out some concepts used […]

  5. […] notice the weird way I’m including JavaScript in the middle of the page, and this is my preferred method for robustly referring to VisualForce elements in JavaScript. Secondly, on line 5 you’ll see […]

  6. 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);

    sapna

    May 7, 2010 at 4:07 pm

    • 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.

      Wes

      May 7, 2010 at 4:40 pm

      • Yes it is within the same pageBlocksection.

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

        sapna

        May 7, 2010 at 4:48 pm

    • WordPress strips some stuff out. Can you post your full code here: http://pastebin.com/. And link to it please.

      Wes

      May 7, 2010 at 4:57 pm

  7. http://pastebin.com/H3fUdCJF
    That is the link. Thank you for the prompt response.

    sapna

    May 7, 2010 at 5:04 pm

    • I made some changes at the same link. Haven’t tested though, let me know if it works.

      Wes

      May 8, 2010 at 10:13 am

  8. I do not see the updated code. Could you please send the link to it ?

    sapna

    May 10, 2010 at 1:55 pm

  9. Here is what is displayed in the alert –

    zip:[object HTMLSpanElement]

    sapna

    May 10, 2010 at 2:19 pm

    • 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).

      Wes

      May 10, 2010 at 9:11 pm

      • Thanks alot!
        It worked by using zip.textContent.

        sapna

        May 10, 2010 at 9:21 pm

  10. 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?

    nishanth

    June 3, 2010 at 6:22 am

    • 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.

      Wes

      June 3, 2010 at 4:20 pm

  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.

    Sim

    June 28, 2010 at 1:58 pm

    • Having a quick look I’d guess that your DOM model changes if you have an Id parm, so your hardcoding of the Ids in the JS call no longer work. I’ve added in some variable declarations that should point you in the right direction. http://pastebin.com/5D9NDt3a

      Wes

      June 28, 2010 at 7:07 pm

      • 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.

        Sim

        June 29, 2010 at 1:47 pm

    • 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 🙂

      Wes

      June 29, 2010 at 2:04 pm

      • Just wanted to confirm if i understood correctly. Thanks once again Wes.

        Sim

        June 30, 2010 at 7:09 am

  12. […] found Wes’ great post, VisualForce Component Ids & Javascript, and took a look at the element Id that Salesforce generated for the SelectList. Based upon the […]

  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?

    Scott Hemmeter

    August 20, 2010 at 6:51 pm

    • 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.

      Scott Hemmeter

      August 20, 2010 at 9:17 pm

  14. Hi Wes, I searched on the internet and found your great post. I have some questions and wonder if you can help me with it. I have posted it on salesforce community forum.

    http://boards.developerforce.com/t5/Visualforce-Development/need-some-help-sample-code-to-retrieve-parent-object-fields/td-p/209078

    Please read the part starting from:” to be more specific,…”

    Thanks very much for your time and help in advance!

    samon

    October 19, 2010 at 8:25 pm

  15. […] VisualForce Component Ids & Javascript […]

  16. […] VisualForce Component Ids & Javascript […]

  17. […] post means that my older posts here and here are now retired in favour of this […]

  18. 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.

    Tobias

    August 19, 2012 at 8:40 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: