If we don't use an
id attribute for a particular component, Visualforce uses a dynamically-generated id, for example, j_id0, j_id0:j_id1. Consider an example, we have specified theid attribute for <apex:inputField id="inputOne"/>. But we haven't specified any id attribute for parent components of inputOne. We can select such a component using jQuery. It is called partial selectors.For example: j$('[id*= inputOne]')<apex:page docType="html-5.0"><!-- HTML5 --></apex:page> <apex:page docType="html-4.0.1-transitional"><!-- HTML 4.0.1 Transitional --></apex:page> <apex:page docType="xhtml-5.0.1-strict"><!-- XHTML 5.0.1 Strict--></apex:page>
The component markup is same as other Visualforce pages. It can be a combination of Visualforce and HTML tags. We can also add customized CSS and JavaScript.All the markup should be defined within the <apex:component> tag. <apex:component
<!—Desire markup here-->
</apex:component>
Our custom component example is a customer's summary with recent orders. Suppose our custom component name is customerSummary, we can use this component in multiple Visualforce pages. The usage is as follows:<apex:page> <c: customerSummary /> </apex:page>
<apex:component controller="CustomerSummaryComponenetController"> <!-- Attribute Definitions --> <apex:attribute name="customerId" Type="String" required="true" description="customer id" assignTo="{!CusID}"/> <apex:attribute name="noOfRecentOrders" Type="Integer" required="true" description="Number of recent orders" assignTo="{!RecentNo}"/> <!-- Attribute Definitions : End --> <!-- Component Definition --> <apex:componentBody > <apex:pageBlock > <apex:pageBlockSection title="Customer Details"> <apex:outputField value="{!CurrentCustomer.Name}"/> <apex:outputField value="{!CurrentCustomer.Address__c}"/> <apex:outputField value="{!CurrentCustomer.Email__c}"/> </apex:pageBlockSection> <apex:pageBlockSection title="Recent Order Details"> <apex:pageBlockTable value="{!RecentOrderList}" var="order"> <apex:column value="{!order.Name}"/> <apex:column value="{!order.Planned_Delivery_Date__c}"/> <apex:column value="{!order.Status__c}"/> </apex:pageBlockTable> </apex:pageBlockSection> </apex:pageBlock> </apex:componentBody> <!-- Component Definition : End --> </apex:component>
public class CustomerSummaryComponenetController{
public String CusID{get;set;}
public Integer RecentNo{get;set;}
public Customer__c CurrentCustomer{
get{
CurrentCustomer = new Customer__c();
CurrentCustomer = [SELECT Id, Name, Address__c, Email__c, Telephone__c FROM Customer__c WHERE Id =: CusID];
return CurrentCustomer;
}
set;
}
public List<Order__c> RecentOrderList{
get{
RecentOrderList = new List<Order__c>();
RecentOrderList = [SELECT Id, Name, Customer__c, Delivered__c, Planned_Delivery_Date__c, Status__c FROM Order__c WHERE Customer__c =: CusID ORDER BY CreatedDate DESC LIMIT :RecentNo];
return RecentOrderList;
}
set;
}
}
<apex:page StandardController="Customer__c"> <c:CustomerSummary customerId="{!Customer__c.Id}" noOfRecentOrders="3"></c:CustomerSummary> </apex:page>
Defining relationships: If there are object relationships to be evaluated in expressions, they become complex expressions. Consider our example, where the
Order__c custom object has a relationship with the Customer__c custom object. The relationship between these two objects is called Orders__r. The Customer__c object has the Email__c field. The same Email__c field will be returned by the following dynamically-cast lookups:Order__c.Customer__c['Email__c']Order__c['Customer__c.Email__c']Order__c['Customer__c']['Email__c']Order__c.Orders__r[Email__c]Order__c[Orders__r.Email__c]Order__c[Orders__r][Email__c]
A dynamic Visualforce page must have a standard controller and further implementations can be done in an associated controller extension. The reason is that Visualforce automatically handles the optimization of the SOQL queries performed by the page's
StandardController or StandardSetController object by loading only the used fields.
When we create a page with static references, the page can identify the fields and objects during compilation. Then the
StandardController object will transform the particular fields and objects into SOQL queries. But the dynamic references are evaluated at runtime and not at compile time. This means that the dynamic references are evaluated after performing the SOQL query of the StandardControllerobject. Therefore, when we use dynamic references and we have to provide some extra information to the controller extension, we can use the addFields() method to add any number of additional fields. This method will pass a list of additional fields to StandardController and those fields will load without giving runtime errors. The usage of the addField() method is as follows:public DynamicOrderExtension(ApexPages.StandardController controller) {
controller.addFields(editableFields);
}
The following example shows the usage of dynamic Visualforce binding. This page shows an order record with some editable fields. Some fields are related to
object(Customer__c). We can understand the usage of dynamic reference with object relationship traversing.<apex:page standardController="Order__c" extensions="DynamicOrderExtension"> <apex:pageMessages /><br/> <apex:form > <apex:pageBlock title="Edit Order" mode="edit"> <apex:pageBlockSection columns="1"> <apex:inputField value="{!Order__c.Name}"/> <apex:repeat value="{!editableFields}" var="f"> <apex:inputField value="{!Order__c[f]}"/> </apex:repeat> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>
The following code is the controller extension of the preceding Visualforce page. The
DynamicOrderExtension controller extension has a list of strings called editableFields and this string list contains some fieldnames of the Order__c object and some fields of related object (Customer__c) ofOrder__c. In this example, editable fields are hardcoded. But we can get information for your dynamic references by using the Apex's Schema.sObjectType methods. This will make a more dynamic and powerful reference. For example, Schema.SobjectType.Order__c.fields.getMap() returns a map with the name of theOrder__c fields. The preceding markup has the <apex:repeat> tag, which is used to loop theeditableFields string list and the <apex:inputField> tag which displays that particular returned string. It represents the field names of the order and the related object's field names. The following markup line displays the dynamic reference:<apex:inputField value="{!Order__c[f]}"/> public with sharing class DynamicOrderExtension { public final Order__c orderDetails { get; private set; } public DynamicOrderExtension(ApexPages.StandardController controller) { String qid = ApexPages.currentPage().getParameters().get('id'); String theQuery = 'SELECT Id, ' + joinList(editableFields, ', ') + ' FROM Order__c WHERE Id = :qid'; this.orderDetails = Database.query(theQuery); controller.addFields(editableFields); } public List<String> editableFields { get { if (editableFields == null) { editableFields = new List<String>(); editableFields.add('Delivered__c'); editableFields.add('Customer__c'); editableFields.add('Planned_Delivery_Date__c'); editableFields.add('Status__c'); editableFields.add('Customer__r.Email__c'); } return editableFields ; } private set; } private static String joinList(List<String> theList, String separator) { if (theList == null) { return null; } if (separator == null) { separator = ''; } String joined = ''; Boolean firstItem = true; for (String item : theList) { if(null != item) { if(firstItem){ firstItem = false; } else { joined += separator; } joined += item; } } return joined; } }
Tip
A Visualforce page can have up to 50 field sets.