Best Practices for Accessing Component IDs

To refer to a Visualforce component in JavaScript or another Web-enabled language you must specify a value for the id attribute for that component. A DOM id is constructed from a combination of the id attribute of the component, and the id attributes of all components that contain the element. This ensures every element has a unique DOM id.

The $Component global variable simplifies references and reduces some of the dependency on the overall page structure. For example, to access a data table with id="tableID" contained in a page block with id="blockID", use the following expression: $Component.blockID.tableID.

You don't need to specify an ID for a component you want to access if it is an ancestor or sibling to the $Component variable in the Visualforce component hierarchy. The system dynamically assigns IDs to the outer components and automatically determines the hierarchy for you.

For example, suppose you want to access a data table component that is contained in an <apex:pageBlock> tag. You only need to specify the ID for the <apex:dataTable> tag. This way, if the page hierarchy ever changes (for example, if an <apex:detail> tag is wrapped around the table), you do not have to change your code.

The following example illustrates the various uses of $Component:
<apex:page>
  <apex:form id="theForm">
    <apex:pageBlock id="thePageBlock">
      <apex:pageBlockSection id="theSection">
        <apex:pageBlockSectionItem id="theSectionItem">All the
        alerts refer to this component</apex:pageBlockSectionItem>
        <!-- Works because this outputPanel has a direct parent 
             with a "theSectionItem" child --> 
    
        <apex:outputPanel onclick="alert('
{!$Component.theSectionItem}');">
            First click here
        </apex:outputPanel>
      </apex:pageBlockSection>
      <apex:pageBlockButtons id="theButtons" location="bottom">
        <!-- Works because this outputPanel has a grandparent ("theSection")
             with a "theSectionItem" child --> 
    
        <apex:outputPanel onclick="alert('
{!$Component.theSection.theSectionItem}');">
            Second click here<br />
        </apex:outputPanel>
        <!-- Works because this outputPanel has a distant parent 
             with a "theForm" child. --> 
    
        <apex:outputPanel onclick="alert('
{!$Component.theForm.thePageBlock.theSection.theSectionItem}');">
            Third click here<br />
        </apex:outputPanel>
      </apex:pageBlockButtons>
    </apex:pageBlock>
    <!-- $Component will reference the common parent of this usage 
         and the target, which is "theForm" --> 
    
    <apex:outputPanel onclick="alert('
{!$Component.thePageBlock.theSection.theSectionItem}');">
        Fourth click here</apex:outputPanel>
  </apex:form>
</apex:page>

Using Unique IDs

Within each hierarchy in a page, the component ID must be unique. However, Salesforce strongly recommends that you use a unique ID for every component in an entire page. For example, suppose you had two data tables in a single page. If both data tables are contained in the same page block they must have unique IDs. If each was contained in a separate page block, it is possible to give them the same component ID. However, the only way you would be able to access the correct data table is by assigning IDs to every component and then specifying the entire hierarchy in your program, rather than letting the system do it automatically. If the page hierarchy ever changes, your program will no longer work.

Iterating with Component IDs

Some components, such as tables and lists, support iteration over a collection of records. After you assign an ID for these types of components, the system assigns a unique “compound ID” to each iteration of the component based on the initial ID.

For example, the following page contains a data table with an ID set to theTable.
<apex:page standardController="Account" recordSetVar="accounts" id="thePage">
    <apex:dataTable value="{!accounts}" var="account" id="theTable">
        <apex:column id="firstColumn">
            <apex:outputText value="{!account.name}"/>
        </apex:column>
        <apex:column id="secondColumn">
            <apex:outputText value="{!account.owner.name}"/>
        </apex:column>
    </apex:dataTable>
</apex:page>
When the page is rendered, the <apex:dataTable> component results in the following HTML:
<table id="thePage:theTable" border="0" cellpadding="0" cellspacing="0">
<colgroup span="2"/>
<tbody>
    <tr class="">
        <td id="thePage:theTable:0:firstColumn">
            <span id="thePage:theTable:0:accountName">Burlington Textiles Corp of America</span>
        </td>
        <td id="thePage:theTable:0:secondColumn">
            <span id="thePage:theTable:0:accountOwner">Vforce Developer</span>
        </td>
    </tr>
    <tr class="">
        <td id="thePage:theTable:1:firstColumn">
            <span id="thePage:theTable:1:accountName">Dickenson</span>
        </td>
        <td id="thePage:theTable:1:secondColumn">
            <span id="thePage:theTable:1:accountOwner">Vforce Developer</span>
        </td>
    </tr>
</table>
Each table cell has a unique ID based on the ID value of the containing components. The first table cell in the first row has the ID thePage:theTable:0:firstColumn, the second cell in the first row has the ID thePage:theTable:0:secondColumn, the first cell in the second row has the ID thePage:theTable:1:firstColumn, and so on.

To refer to all entries in a column, you have to iterate across the table rows, referring to each <td> element that has an ID following the format of the column.

The same type of ID generation is done for elements within the table cells. For example, the account name in the first row is generated as a span with the ID thePage:theTable:0:accountName. Notice that ID does not include the value of the ID for the column it is in.

© Copyright 2000–2012 salesforce.com, inc. All rights reserved.
Various trademarks held by their respective owners.