Disable Visualforce Buttons When Processing – apex:actionStatus

27 Dec

It is very handy to disable buttons after they have been pressed. This lets the user know that the button was in fact pressed, and it prevents the button’s action from being executed multiple times. The Visulforce component apex:actionStatus gives us an easy way to accomplish this. Here are some things to take note of in the example.

  • The command button must have a rerender parameter
  • Command buttons must be in an apex:outputPanel, so both buttons appear on the page when each apex:facet is active.
  • The action status will only disable one set of buttons for a apex:pageBlock at a time. If ‘both’ is specified for the button location, only the clicked set of buttons on top or bottom will be disabled while processing. I usually select only one location to prevent additional button clicks.
  • Add the immediate=”true” attribute to the Cancel. This bypasses Visualforce validation that would normally fire on the form.

active buttons
disabled buttons

ExamplePage.page


 
  
  

    
    
     
      
       
        
        
       
      
      
       
        
        
       
      
     
     
    

  

 

ExamplePageController.cls

public with sharing class ExamplePageController {

  public ExamplePageController() {
    // do constructor logic
  }
  
  public PageReference DoSave() {
    // do save logic
    return null;
  }
    public PageReference DoCancel() {
    // do cancel logic
    return null;
  }
}

Multiselect Picklists for User Search and Selection using Apex and Visualforce

9 Dec

Below is a component that will allow you to search and select Users. It was created to mimic the experience of selecting multiple users in the Task creation window. However, it would be easy to change the reference from the User object to almost any other object.

An initial list of selected users can be assigned by passing an Id list in the component attribute aInitialRightList. The list referenced in the aCurrentRightList attribute will be updated anytime entries in the right multiselect picklist change. The aWidth attribute accepts px or %, and it sets the width of the entire component.

I’d like to thank those who posted sample code that helped me with the multiselect picklist component. I borrowed ideas and code from the following:
Custom Multi-Select picklist field in Visualforce
A Multiselect Picklist Visualforce Component

Multi Select Picklist Visualforce Component Example

UserMultiSelectComponent.component


  
  
  
  
  
    
 
  
    
      
Search:  
{!aLeftLabel} {!aRightLabel}


UserMultiSelectComponentController.cls

public with sharing class UserMultiSelectComponentController {
  public static final String USERTYPE_STD = 'Standard';
  public list InitialRightList {get;set;}
  public list CurrentRightList {get;set;}
  public String SearchText {get;set;}
  public list LeftSelectedList {get;set;}
  public list RightSelectedList {get;set;}
  map LeftOptionMap = new map();
  map RightOptionMap = new map();
  
  /****
  * Controller - instantiate lists 
  ****/
  public UserMultiSelectComponentController() {
    LeftSelectedList = new list();
    RightSelectedList = new list();
  }
  
  /****
  * ClickRight - Right pointing arrow was clicked. Move selected options to the right box.
  ****/
  public PageReference ClickRight(){
    RightSelectedList.clear();
    for(String s : LeftSelectedList){
      if (LeftOptionMap.containsKey(s)) {
        RightOptionMap.put(s, LeftOptionMap.get(s));        
      }
      LeftOptionMap.remove(s);
    }
    return null;
  }

  /****
  * ClickLeft - Left pointing arrow was clicked. Move selected options to the left box.
  ****/     
  public PageReference ClickLeft(){
    LeftSelectedList.clear();
    for(String s : RightSelectedList){
      if (RightOptionMap.containsKey(s)) {
        LeftOptionMap.put(s, RightOptionMap.get(s));        
      }
      RightOptionMap.remove(s);
    }
    return null;
  }

  /****
  * getLeftOptionList - return SelectOptions for the left/unselected box
  ****/      
  public list getLeftOptionList(){
    list TempOptionList = new list();
    list TempValueList; 
  
    TempValueList = LeftOptionMap.values();
    TempValueList.sort();  // sort by name
    for (User u : TempValueList) { 
      TempOptionList.add(new SelectOption(u.Id, u.Name));
    }
    return TempOptionList;
  }

  /****
  * getRightOptionList - return SelectOptions for the right/selected box
  ****/ 
  public list getRightOptionList(){
    list TempOptionList = new list();
    list TempValueList;
    list UserList;

    //clear is used instead of new list, so the list maintains the pointer to the ExamplePageController list
    CurrentRightList.clear();  
    
    // load initially selected records into the right box 
    if (InitialRightList != null && InitialRightList.size() > 0) {
      UserList = [Select Name, Id, IsActive, UserType From User where IsActive=true and UserType = :USERTYPE_STD and Id IN :InitialRightList limit 500];
      for (User u : UserList) {
        RightOptionMap.put(u.Id, u);
      }
      InitialRightList.clear();
    }
    
    TempValueList = RightOptionMap.values();
    TempValueList.sort();  // sort by name
    for (User u : TempValueList) { 
      TempOptionList.add(new SelectOption(u.Id, U.Name));
      CurrentRightList.add(u.Id);
    }   
    return TempOptionList;
  }

  /****
  * Find - Search for user records by name, and add them to the left box
  ****/ 
  public PageReference Find(){
    String TempSearchText;
    list UserList;
    
    TempSearchText = '%' + SearchText + '%';
    UserList = [Select Name, Id, IsActive, UserType From User where IsActive=true and UserType = :USERTYPE_STD and Name like :TempSearchText limit 500];
    
    LeftOptionMap.clear();
    for (User u : UserList) {
      if (!RightOptionMap.containsKey(u.Id)) {
        LeftOptionMap.put(u.Id, u);
      }
    }
    
    return null;
  }
}

ExamplePage.page


  
    
      
    
    
    
      
        

ExamplePageController.cls

public with sharing class ExamplePageController {
  public list InitialList  {get;set;}
  public list CurrentList  {get;set;}

  public ExamplePageController() { 
    InitialList = new list();
    InitialList.add(UserInfo.getUserId());
    CurrentList = new list();
  }
}

UserMultiSelectComponentControllerTest.cls

@isTest
private class TestUserMultiSelectComponentController {
  static testMethod void TestUserMultiSelect() {
    list TempOptionList;
    list UserList;
    UserMultiSelectComponentController UMSCcontroller = new UserMultiSelectComponentController();
        
    // set initial user
    UserList = [Select Name, Id, IsActive, UserType From User where IsActive=true and UserType = :UserMultiSelectComponentController.USERTYPE_STD limit 1];
        
    system.Test.startTest(); 
        
    // instantiate lists that would be passed in
    UMSCcontroller.InitialRightList = new list();
    UMSCcontroller.CurrentRightList = new list();
       
    // initial list item should show in right list, left should be empty
    UMSCcontroller.InitialRightList.add(UserList[0].Id);
    TempOptionList = UMSCcontroller.getLeftOptionList();
    system.assertEquals(0, TempOptionList.size());
    TempOptionList = UMSCcontroller.getRightOptionList();
    system.assertEquals(UserList[0].Id, TempOptionList[0].getValue());  // returned option list
    system.assertEquals(UserList[0].Id, UMSCcontroller.CurrentRightList[0]);  // current right list
        
    // run find method, this will add entries to the left LeftOptionMap that get put into a list in getLeftOptionList
    UMSCcontroller.SearchText = '';  // so search text is not null
    UMSCcontroller.Find(); // assumes there are 2 or more standard users
    TempOptionList = UMSCcontroller.getLeftOptionList();
    system.assertNotEquals(0, TempOptionList.size());  //not 0
     
    // Select entry to move to right box
    UMSCcontroller.LeftSelectedList.add(TempOptionList[0].getValue());
    UMSCcontroller.ClickRight();
    TempOptionList = UMSCcontroller.getRightOptionList();  // update CurrentRightList with 2 selected ids
    system.assertEquals(2, UMSCcontroller.CurrentRightList.size()); 
       
    // Select entry to move to left box
    UMSCcontroller.RightSelectedList.add(UserList[0].Id);
    UMSCcontroller.ClickLeft();
    TempOptionList = UMSCcontroller.getRightOptionList();  // update CurrentRightList with 1 selected ids
    system.assertEquals(1, UMSCcontroller.CurrentRightList.size());
    system.assertEquals(TempOptionList[0].getValue(), UMSCcontroller.CurrentRightList[0]);
     
    system.Test.stopTest();
  }
}

Record ID and Data Retrieval from a VisualForce Controller Extension without a SOQL statement

26 Nov

Retrieve field data for a record using the Standard Controller object in a Controller Extension class

public with sharing class MyController {.
  Account MyAccount;
  Id MyId;

  public MyController(ApexPages.StandardController controller) {
    list MyFieldList;  
    
    // get the record
    // passing a list of field names to the standard controller will cause 
    // the standard controller to retrieve the field data of the record
    MyFieldList = new list{'Id', 'Name', 'BillingCity', 'BillingState', 'MyCustomField__c'};
    controller.addFields(MyFieldList);
    MyAccount= (Account)controller.getRecord();

     // another way to get more fields. use the addFields method
     // by default only fields referenced in the VisualForce page are retrieved.
     controller.addFields(new list{'ShippingCity', 'ShippingState'});

     // get the record id
     // this is the record id of the query string in the URL
     MyId = controller.getId()
  }
}

Salesforce Documentation:
Standard Controller Class
StandardController Instance Methods

Visualforce Help Text and a Popup Tool Tip

21 Oct

Visualforce Field Help Text

The help icon can be added to a Visualforce field within an apex:pageBlockSectionItem. Access the help text using the $ObjectType api. Put it in the helptext attribute of the apex:pageBlockSectionItem.

{!$ObjectType.Account.Fields.Phone.InlineHelpText}

      
      

Easy Hover Tooltip

The following may help if you are not using the apex:pageBlockSectionItem. I’ve used this technique in the past to put help text on an image in a apex:pageBlockTable and on plain text in a page.

Example:

Hover Over Me
your message here

 
  div.tooltip {
    width: 195px;
    float: left;
  }
  div.tooltip:hover {
    background: #ffffff;
    text-decoration: none;
  } /*BG color is a must for IE6*/
  div.tooltip span {
    display: none;
    padding: 2px 3px;
    margin-left: 8px;
    width: 195px;
  }
  div.tooltip:hover span {
    display: inline;
    position: absolute;
    border: 1px solid #cccccc;
    background: #FFC;;
    color: #000000;
  }
Hover Over Me your message here

Thanks to www.kollermedia.at/archive/2008/03/24/easy-css-tooltip/ for providing an easy way to add tooltip help. He does it by putting the style on the link tag instead of the div.

March 16, 2014: Here is another tutorial that explains how to do a popup tool tip. Tutsplus – Tooltip

Define and Initialize a Map, List, and Set in Apex

20 Oct

The syntax for defining a list, map, and set collection with initial values sometimes slips my mind. The lack of () throws me off, so this post is to help out my future self.

List Definition

public list MyList = new list {'AAA', 'AAA', 'BBB', 'BBB', 'CCC'};

Set Definition

public set MySet = new <set>{'A', 'B', 'C', 'D', 'E', 'F', 'G'};

Map Definition

public map<String, String> MyMap = new map<String, String> {'KeyValueA' => 'ValueA', 
                                                            'KeyValueB' => 'ValueB', 
                                                            'KeyValueC' => 'ValueC'};

Defining a List of Maps

public list<map<String, String>> MyListOfMaps = new list<map<String, String>> 
  {new map<String, String>
     {'KeyValueA' => 'ValueA',
      'KeyValueB' => 'ValueB',
      'KeyValueC' => 'ValueC'
     },
   new map<String, String>
     {'KeyValueA' => 'ValueA'
     },
   new map<String, String>
     {'KeyValueA' => 'ValueA',
      'KeyValueB' => 'ValueB'
     }
  };

Defining a Map of Lists

public map<String, list> MyMap = new map<String, list>
  {'KeyValue1' => new list {'ValueA', 'ValueB', 'ValueC'},
   'KeyValue2' => new list {'ValueD', 'ValueE', 'ValueF'},
   'KeyValue3' => new list {'ValueG', 'ValueH', 'ValueI'}
  };

Defining a Map of Maps

public map<String, map<String, String>> MyMap = new map<String, map<String, String>>
  {'KeyValue1' => new map<String, String>
     {'KeyValueA' => 'ValueA',
      'KeyValueB' => 'ValueB',
      'KeyValueC' => 'ValueC'
     },
   'KeyValue2' => new map<String, String>
     {'KeyValueA' => 'ValueA'
     },
   'KeyValue3' => new map<String, String>
     {'KeyValueA' => 'ValueA',
      'KeyValueB' => 'ValueB'
     }
  };

Sample logic to retrieve the nested Map’s value

This function accepts Param1 as the key for the outer map. Param2 is the key for the inner map. TheMap is a map that contains a nested map which will be worked with. First, we see if there is a key value in the outer map that matches Param1. When it contains the key, the next statement creates a reference to the inner map in the variable TempMap. TempMap is checked for the value of Param2, and the value is returned when found. Finally, null is returned when there is not a match.

public static String GetInnerMapValue(String Param1, String Param2, map<String, map<String, String>> TheMap) {
  map<String, String> TempMap;
  if (TheMap.containsKey(Param1)) {
    TempMap = TheMap.get(Param1);
    if (TempMap.containsKey(Param2)  return TempMap.get(Param2);
  }
  // map values were not found, so return something else
  return null;
}