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

Multiselecting related objects

One task that users often find unwieldy when implementing Salesforce is setting up the sObjects to represent many-to-many relationships. A junction object allows a single instance of one sObject type to be related to multiple instances of another sObject type and vice versa.

This requires the user to create a new instance of the junction object and populate master-detail fields to associate two sObjects with each other, resulting in a large number of clicks and page transitions.

In this recipe, we will create a custom object – account group – that acts as a container for multiple accounts. We will then create a page that allows a number of accounts to be associated with a single custom sObject. We will use junction objects for the relationship to allow a single account to be related to multiple account groups, and a single account group to be associated with multiple accounts. A custom Visualforce component will manage the action of presenting the available accounts and allowing the user to choose which to relate with the account group. The component will use the mechanism described in the Updating attributes in component controllers recipe to make the selected values available to the page controller via a custom string container class.

Getting ready

This recipe requires two custom sObjects: the account group, and the junction object between an account group and an account.

  1. First, create the account group custom sObject by navigating to Your Name | Setup | Develop | Objects.
  2. Click on the New Custom Object button.
  3. Enter Account Group in the Label field.
  4. Enter Account Groups in the Plural Label field.
  5. Select the Starts with vowel sound box.
  6. Leave all other input values at their defaults and click on the Save button.
  7. Next, create the junction object to associate an account group with an account by navigating to Your Name | Setup | Develop | Objects.
  8. Click on the New Custom Object button.
  9. Enter Account Group JO in the Label field.
  10. Enter Account Group JOs in the Plural Label field.
  11. Select the Starts with vowel sound box.
  12. Leave all other input values at their defaults and click on the Save button.
  13. On the resulting page, create the master-detail relationship for the account group by scrolling down to the Custom Fields and Relationships section and clicking on the New button.
  14. On the next page, Step 1. Choose the field type, select the Master-Detail Relationship from the Data Type radio buttons and click on the Next button.
  15. On the next page, Step 2. Choose the related object, choose Account Group from the Related To picklist and click on the Next button.
  16. On the next page, Step 3. Enter the label and name for the lookup field, leave all the fields at their default values and click on the Next button.
  17. On the next page, Step 4. Establish field-level security for reference field, leave all the fields at their default values and click on the Next button.
  18. On the next page, Step 5. Add reference field to page layouts, leave all the fields at their default values and click on the Next button.
  19. On the final page, Step 6. Add Custom Related Lists, leave all the fields at their default values and click on the Save button.
  20. Next, create the master-detail relationship for the account by scrolling down to the Custom Fields and Relationships section and click on the New button.
  21. On the next page, Step 1. Choose the field type, select the Master-Detail Relationship from the Data Type radio buttons and click on the Next button.
  22. On the next page, Step 2. Choose the related object, choose Account from the Related To picklist and click on the Next button.
  23. On the next page, Step 3. Enter the label and name for the lookup field, leave all the fields at their default values and click on the Next button.
  24. On the next page, Step 4. Establish field-level security for reference field, leave all the fields at their default values and click on the Next button.
  25. On the next page, Step 5. Add reference field to page layouts, leave all the fields at their default values and click on the Next button.
  26. On the final page, Step 6. Add Custom Related Lists, leave all the fields at their default values and click on the Save button.

How to do it…

  1. Create the custom string container class 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 StringContainer.cls Apex class from the code download into the Apex Class area.
  4. Click on the Save button.
  5. Next, create the custom controller for the Visualforce component by navigating to the Apex Classes setup page by clicking on Your Name | Setup | Develop | Apex Classes.
  6. Click on the New button.
  7. Paste the contents of the MultiSelectRelatedController.cls Apex class from the code download into the Apex Class area.
  8. Click on the Save button.
  9. Next, navigate to the Visualforce Components setup page by clicking on Your Name | Setup | Develop | Components.
  10. Click on the New button.
  11. Enter MultiSelectRelated in the Label field.
  12. Accept the default MultiSelectRelated that is automatically generated for the Name field.
  13. Paste the contents of the MultiSelectRelated.component file from the code download into the Visualforce Markup area and click on the Save button.
  14. Next, create the custom controller for the Visualforce page by navigating to the Apex Classes setup page by clicking on Your Name | Setup | Develop | Apex Classes.
  15. Click on the New button.
  16. Paste the contents of the AccountGroupController.cls Apex class from the code download into the Apex Class area.
  17. Click on the Save button.
  18. Finally, create the Visualforce page by navigating to the Visualforce setup page by clicking on Your Name | Setup | Develop | Pages.
  19. Click on the New button.
  20. Enter AccountGroup in the Label field.
  21. Accept the default AccountGroup that is automatically generated for the Name field.
  22. Paste the contents of the AccountGroup.page file from the code download into the Visualforce Markup area and click on the Save button.
  23. Navigate to the Visualforce setup page by clicking on Your Name | Setup | Develop | Pages.
  24. Locate the entry for the AccountGroup page and click on the Security link.
  25. On the resulting page, select which profiles should have access and click on the Save button.

How it works…

Opening the Visualforce page in your browser displays the account group create page: https://<instance>/apex/AccountGroup.

Here, <instance> is the Salesforce instance specific to your organization, for example, na6.salesforce.com.

The chosen account IDs are stored as semi-colon separated values in a property of the page controller. The page controller constructor extracts all accounts and creates a standard SelectOption class for each one.

accountOptions=new List<SelectOption>();
for (Account acc : [select id, Name from Account])
{
  accountOptions.add(new SelectOption(acc.id, acc.name));
}

The custom component controller contains two collections of options: available and chosen. The component iterates the full set of account options and adds the option to available or chosen depending on whether the account ID is present in the semi-colon separated string of chosen IDs.

availableItems=new List<SelectOption>();
chosenItems=new List<SelectOption>();
        
for (SelectOption sel : allOptions)
{
  String selId=sel.getValue();
  if (selected.value.contains(selId+';'))
  {
    chosenItems.add(sel);
  }
  else
  {
    availableItems.add(sel);
  }
}

Accounts can be moved between the Available and Selected lists by highlighting the options and clicking on the > or < buttons.

Each button invokes an action method in the component controller that adds or removes the account IDs from the semi-colon separated chosen string, and then rebuilds the available and chosen lists.

Clicking on the Save button creates the account group record and a junction object for each account ID in the chosen string.

public PageReference save()
{
  insert accountGroup;
  List<Account_Group_JO__c> agJOs=
        new List<Account_Group_JO__c>();

  for (String accId : chosenAccounts.value.split(';'))
  {
    Account_Group_JO__c agJO=
      new Account_Group_JO__c(
          Account_Group__c=accountGroup.id, 
          Account__c=accId);
    agJOs.add(agJO);
  }
    
  insert agJOs;
    
  return new PageReference('/' + accountGroup.id);
}