Passing Parameters with a CommandButton

This post is a slight tweak of yesterday's post, Passing Parameters with a CommandLink. In theory you should just be able to switch out the CommandLink component with a CommandButton component and be golden. However, not so fast. There seem to still be a bug with the CommandButton component.

Here is the Visualforce page with the CommandButton instead of the CommandLink:

<apex:page standardController="Contact" extensions="CommandButtonParamController">
  <apex:form >

  <apex:commandButton value="Process Nickname" action="{!processButtonClick}">
  <apex:param name="nickName"
    value="{!contact.firstname}"
    assignTo="{!nickName}"/>
  </apex:commandButton>

  </apex:form>
</apex:page>

As with the CommandLink, when the user clicks the button the setters should fire and then call the processButtonClick() method to allow further publishing. However, the setter for nickName is never called!

public with sharing class CommandButtonParamController {

  // an instance varaible for the standard controller
  private ApexPages.StandardController controller {get; set;}
 // the object being referenced via url
  private Contact contact {get;set;}
  // the variable being set from the commandbutton
  public String nickName {
   get;
   // *** setter is NOT being called ***
   set {
    nickName = value;
    System.debug('value: '+value);
   }
  }

  // initialize the controller
  public CommandButtonParamController(ApexPages.StandardController controller) {

  //initialize the stanrdard controller
  this.controller = controller;
  // load the current record
  this.contact = (Contact)controller.getRecord();

  }

  // handle the action of the commandButton
  public PageReference processButtonClick() {
   System.debug('nickName: '+nickName);
   // now process the variable by doing something...
   return null;
  }

}

Wes Nolte has done a great job on his blog and the Salesforce.com message boards pointing out the problem and workarounds. A popular option is using the CommandLink but styling it to look like a CommandButton.

You can make the CommandButton function as advertised if you use a rerender attribute and hidden pageBlock component. If you run the Visualforce page below with these modifications the setter will actually fire and set the value of nickName correctly.

<apex:page standardController="Contact" extensions="CommandButtonParamController">
  <apex:form >

  <apex:commandButton value="Process Nickname" action="{!processButtonClick}" rerender="hiddenBlock">
  <apex:param name="nickName"
    value="{!contact.firstname}"
    assignTo="{!nickName}"/>
  </apex:commandButton>

  <apex:pageBlock id="hiddenBlock" rendered="false"></apex:pageBlock>

  </apex:form>
</apex:page>