Newer Version Available
Using Dynamic References with Standard Objects
Use dynamic Visualforce bindings to construct simple, reusable pages with a known set of fields you want to access. This approach has the advantage of easily customizing which fields are pertinent for a user to work with.
The next two examples are deliberately simple for instructional purposes. See Using Dynamic References for a User-Customizable Page for a more advanced example that makes fuller use of dynamic Visualforce.
A Simple Dynamic Form
The following example demonstrates the simplest way to construct a Visualforce page that uses dynamic references.
- The DynamicAccountFieldsLister controller extension creates a list of strings called editableFields. Each string maps to a field name in the Account object.
- The editableFields list is hard-coded, but you can determine them from a query or calculation, read them from a custom setting, or otherwise providing a more dynamic experience. This is what makes dynamic references powerful.
- DynamicAccountEditor markup uses an <apex:repeat> tag to loop through the strings returned by editableFields.
- The <apex:inputField> tag displays each field in editableFields by referencing the f iteration element, which represents the name of a field on Account. The dynamic reference {!Account[f]} actually displays the value on the page.
Ensuring that Fields in Dynamic References are Loaded by a Standard Controller
Visualforce automatically optimizes the SOQL query performed by a page’s StandardController (or StandardSetController), loading only the fields which are actually used on a page. When you create a Visualforce page with static references to objects and fields, the fields and objects can be known in advance. When the page is saved, Visualforce is able to determine and save which objects and fields need to be added to the SOQL query that the StandardController will perform later, when the page is requested.
Dynamic references are evaluated at runtime, after the SOQL query is run by the StandardController. If a field is only used via a dynamic reference, it won’t be automatically loaded. When that dynamic reference is later evaluated, it will resolve to data which is missing, the result of which is a SOQL error. You must provide some extra information to the controller, so that it knows what fields and related objects to load.
This works well for pages when the complete list of fields to load can be known when the controller extension is instantiated. If the list of fields can’t be determined until later in the request processing, you can call reset() on the controller and then add the fields. This will cause the controller to send the revised query. Using Dynamic References for a User-Customizable Page provides an example of this technique.
Dynamic References to Related Objects
This example creates a Visualforce page for a case record, with certain fields that are editable. Some of the fields displayed are from a related object, showing how you can use dynamic references to traverse relationships.
- In the controller extension, the constructor performs its own SOQL query for the object to display. Here it’s because the page’s StandardController doesn’t load related fields by default, but there are many different use cases for needing a customized SOQL query. The query result is made available to the page through the property caseFieldList. There’s no requirement to perform the query in the constructor—it can just as easily be in the property’s get method.
- The SOQL query specifies the fields to load, so it’s not necessary to use addFields() which was needed in A Simple Dynamic Form.
- The SOQL query is constructed at run time. A utility method converts the list of field names into a string suitable for use in a SOQL SELECT statement.
- In the markup, the form fields are displayed by iterating through the field names using <apex:repeat>, and using the field name variable cf in a dynamic reference to get the field value. Each field is potentially written by two components—<apex:outputText> and <apex:inputText>. The render attribute on these tags controls which of the two actually displays: if the field name contains the string “Contact,” then the information is rendered in an <apex:inputText> tag, and if it doesn’t, it’s rendered in an <apex:outputText>.
Using Dynamic References for a User-Customizable Page
The full potential of Visualforce dynamic bindings is in building pages without knowing which fields are available on an object. The following example demonstrates this capability with a list of accounts that can be customized without knowing any of the fields on the Account object, except for the Name field required on all objects. This is made possible by using the Schema.SobjectType.Account.fields.getMap() to retrieve the list of fields that exist on the object, and Visualforce dynamic references.
- The standard controller methods addFields() and reset() are used in the show() method, which is the method that returns back to the list view. They are necessary because the list of fields to display may have changed, and so the query that loads data for display needs to be re-executed.
- Two action methods, customize() and show(), navigate from the list view to the customization form and back again.
- Everything after the navigation action methods deals with the customization form. These methods are broadly broken into two groups, noted in the comments. The first group provides the List<SelectOption> lists used by the customization form, and the second group handles the two buttons that move items from one list to the other.
The second <apex:pageBlock> holds a <apex:pageBlockTable> that has columns added in a <apex:repeat>. All columns in the repeat component use a dynamic reference to account fields, {!acct[f]}, to display the user’s custom-selected fields.
- This page uses the same standard controller as the list view, even though no accounts are being displayed. This is required to maintain the view state, which contains the list of fields to display. If this form saved the user’s preferences to something permanent, like a custom setting, this wouldn’t be necessary.
- The first list is populated by a call to the getUnSelectedOptions() method, and when the form is submitted (via either of the two <apex:commandButton> components), the values in the list that are selected at time of form submission are saved into the selected property. Corresponding code handles the other list.
- These “delta” lists of fields to move are processed by the doAdd() or doRemove() method, depending on which button was clicked.
- View the customizable list in the default state, with only the account name
field displayed.
Click Customize List. - The display preferences screen is shown.
Move
some fields into the list on the right, and click Show These
Fields. - The customized list view is displayed.