Visualforce Development Cookbook
上QQ阅读APP看书,第一时间看更新

Updating attributes in component controllers

Updating fields of sObjects passed as attributes to custom components is straightforward, and can be achieved through simple merge syntax statements. This is not so simple when the attribute is a primitive and will be updated by the component controller, as parameters are passed by value, and thus, any changes are made to a copy of the primitive. For example, passing the name field of a contact sObject, rather than the contact sObject itself, would mean that any changes made in the component would not be visible to the containing page.

In this situation, the primitive must be encapsulated inside a containing class. The class instance attribute is still passed by value, so it cannot be updated to point to a different instance, but the properties of the instance can be updated.

In this recipe, we will create a containing class that encapsulates a Date primitive and a Visualforce component that allows the user to enter the date via day/month/year picklists. A simple Visualforce page and controller will also be created to demonstrate how this component can be used to enter a contact's date of birth.

Getting ready

This recipe requires a custom Apex class to encapsulate the Date primitive. To do so, perform the following steps:

  1. First, create the class that encapsulates the Date primitive by navigating to the Apex Classes setup page by clicking on Your Name | Setup | Develop | Apex Classes.
  2. Click on the New button.
  3. Paste the contents of the DateContainer.cls Apex class from the code download into the Apex Class area.
  4. Click on the Save button.

How to do it…

  1. First, create the custom component controller by navigating to the Apex Classes setup page by clicking on Your Name | Setup | Develop | Apex Classes.
  2. Click on the New button.
  3. Paste the contents of the DateEditController.cls Apex class from the code download into the Apex Class area.
  4. Click on the Save button.
  5. Next, create the custom component by navigating to the Visualforce Components setup page by clicking on Your Name | Setup | Develop | Components.
  6. Click on the New button.
  7. Enter DateEdit in the Label field.
  8. Accept the default DateEdit that is automatically generated for the Name field.
  9. Paste the contents of the DateEdit.component file from the code download into the Visualforce Markup area and click on the Save button.
  10. Next, create the Visualforce page controller extension by navigating to the Apex Classes setup page by clicking on Your Name | Setup | Develop | Apex Classes.
  11. Click on the New button.
  12. Paste the contents of the ContactDateEditExt.cls Apex class from the code download into the Apex Class area.
  13. Click on the Save button.
  14. Finally, create a Visualforce page by navigating to the Visualforce setup page by clicking on Your Name | Setup | Develop | Pages.
  15. Click on the New button.
  16. Enter ContactDateEdit in the Label field.
  17. Accept the default ContactDateEdit that is automatically generated for the Name field.
  18. Paste the contents of the ContactDateEdit.page file from the code download into the Visualforce Markup area and click on the Save button.
  19. Navigate to the Visualforce setup page by clicking on Your Name | Setup | Develop | Pages.
  20. Locate the entry for the ContactDateEdit.page file and click on the Security link.
  21. On the resulting page, select which profiles should have access and click on the Save button.

How it works…

Opening the following URL in your browser displays the ContactDateEdit page: https://<instance>/apex/ContactDateEdit?id=<contact_id>.

Here, <instance> is the Salesforce instance specific to your organization, for example, na6.salesforce.com, and <contact_id> is the ID of any contact in your Salesforce instance.

The Visualforce page controller declares a DateContainer property that will be used to capture the contact's date of birth.

public DateContainer dob {get; set;}
private Contact cont;
private ApexPages.StandardController stdCtrl {get; set;}
  
public ContactDateEditExt(ApexPages.StandardController std)
{
  stdCtrl=std;
  cont=(Contact) std.getRecord();
  dob=new DateContainer(cont.BirthDate);
}
Note

Note that as DateContainer is a class, it must be instantiated when the controller is constructed.

The custom component that manages the Date of Birth section defines the following two attributes:

  • A required attribute of type DateContainer, which is assigned to the dateContainer property of the controller
  • The title of for the page block section that will house the picklists; as this is a reusable component, the page supplies an appropriate title
    Note

    Note that this component is not tightly coupled with a contact date of birth field; it may be used to manage a date field for any sObject.

    <apex:attribute type="DateContainer" name="dateContainerAtt"
        description="The date" assignTo="{!dateContainer}"
        required="true" />
    <apex:attribute type="String"
        description="Page block section title" name="title" />

The component controller defines properties for each of the day, month, and year elements of the date. Each setter for these properties attempts to construct the date if all of the other elements are present. This is required as there is no guarantee of the order in which the setters will be called when the Save button is clicked and the postback takes place.

public Integer year {get; 
    set {
          year=value;
          updateContainer();
          }
    }
  
private void updateContainer()
{
  if ( (null!=year) && (null!=month) && (null!=day) )
  {
    Date theDate=Date.newInstance(year, month, day);
    dateContainer.value=theDate;
  }
}

When the contained date primitive is changed in the updateContainer method, this is reflected in the page controller property, which can then be used to update a field in the contact record.

public PageReference save()
{
  cont.BirthDate=dob.value;
  
  return stdCtrl.save();
}

See also

  • The Passing attributes to components recipe in this chapter shows how an sObject may be passed as an attribute to a custom component.
  • The Adding a custom datepicker to a form recipe in Chapter 3, Capturing Data Using Forms presents an alternative solution to capturing a date outside of the standard Salesforce range.