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,
- 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.
- 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.
this is good, thanks!!
mallika
July 8, 2009 at 3:59 pm
This worked great. May I ask some assistance, please.
… some parts missing …
Thanks, Brian
Brian
July 14, 2009 at 12:30 pm
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
[…] 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 […]
VisualForce Form Validation Enhanced « The Silver Lining
March 2, 2010 at 11:44 am
[…] 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 […]
Client-Side VisualForce Pagination with Pajinate « The Silver Lining
April 21, 2010 at 9:21 pm
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
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
I do not see the updated code. Could you please send the link to it ?
sapna
May 10, 2010 at 1:55 pm
Sure it’s here: http://pastebin.com/AGr5QRuU
Wes
May 10, 2010 at 2:13 pm
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
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
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
[…] 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 […]
Why is this so DOM Hard? | Jeff Douglas - Technology, Coding and Bears... OH MY!
August 11, 2010 at 1:29 pm
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
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
[…] VisualForce Component Ids & Javascript […]
jQuery UI datepicker in Visualforce | Avishaybl's Blog
January 11, 2011 at 3:12 pm
[…] VisualForce Component Ids & Javascript […]
jQuery UI datepicker in Visualforce « Avishaybl's Blog
January 11, 2011 at 4:15 pm
[…] post means that my older posts here and here are now retired in favour of this […]
Salesforce: A better way to work with Visualforce Component Ids and JavaScript « The Silver Lining
June 24, 2011 at 2:36 pm
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
That is very true! In some cases it would break salesforce’s styling but in most cases this would work. At the top of this post I’ve noted that this approach is old and I no longer use it, there’s a better way that I’ve shown here: https://th3silverlining.com/2011/06/24/salesforce-a-better-way-to-work-with-visualforce-component-ids-and-javascript/
Wes
August 19, 2012 at 1:28 pm