+ Start a Discussion
Steve ChadbournSteve Chadbourn 

How to use apex:param and assignTo

I'm using a param component nested inside a commandLink and want to set a controller variable to its value but I can't seem to get it to work.
 
Here is the visualforce code:
 
Code:
<apex:commandLink action="{!test}" value="Select">
 <apex:param assignTo="{!myClient}" value="{!client.Full_Name__c}"/>
</apex:commandLink>

And here is the controller code:
Code:
public class MyController
{
 String myClient;

    public void setMyClient(String s)
    {
     myClient = s;
    }
}

I get an error of Unknown property MyController.myClient.
 
Any ideas?
 
 
mikefmikef
Steve:

Hi just to start this off, I am learning how to code in VisualForce right now, and I am looking to do almost the same thing.

I am searching the boards for answers and came to your post.

In the help doc it states that param can only be a child of an outPutLink...
"A parameter for the parent component. The param component can only be a child of an outputLink, outputText, or a actionFunction component." taken from the apex page components page.

I see you are using a commandLink, try using the outPutLink.

Please post a reply if that worked or not.
dchasmandchasman
<apex:commandLink> does support child <apex:params> and assignTo - the problem you're hitting can be fixed by adding a getter method for your MyClient property, e.g.:
public String getMyClient() {
return myClient;
}

visualforce does not currently support the concept of write only properties (it is on the bug list) and the page compiler is getting confused by the lack of a getter method.


Message Edited by dchasman on 03-22-2008 07:06 AM
Steve ChadbournSteve Chadbourn

Thanks I'll give that a try.

Mikef - there is an error in the Visualforce documentation. On page 161 it does indeed specify that param can only be a child of an outputLink or outputText component. On page 24 though it specifies that param can be incuded in other tags such as include, commandButton and commandLink.

mikefmikef
Thanks for the doc update, that means the component help link and the VisualForce doc are different.

Steve ChadbournSteve Chadbourn

While I don't get an error anymore thanks to adding a getter, I am getting strange behaviour so I'll explain what I'm trying to do and show how I'm attempting it and hopefully someone can correct my code or come up with a better way to do it.

I need to display a list of client information (ultimately returned from a web service) and allow the user to select one of the rows.

I have created a custom object with 3 fields, all text.

Here is the controller code:

 
public class listTestController
{
 String myClient;
 
 public PageReference selectClient()
 {
  return null;
 }

 public Client_Search_Result__c[] getClientResults()
 {
  Client_Search_Result__c[] clientResults = new Client_Search_Result__c[]{};
  
  Client_Search_Result__c client1 = new Client_Search_Result__c();
  client1.Full_Name__c = 'Fred Jones';
  client1.Address__c = '10 Main Street, Auckland';
  client1.Date_of_Birth__c = '10/10/1970';
  clientResults.add(client1);
  
  Client_Search_Result__c client2 = new Client_Search_Result__c();
  client2.Full_Name__c = 'Peter Smashing';
  client2.Address__c = '99 Hell Street, Wellington';
  client2.Date_of_Birth__c = '10/10/1970';
  clientResults.add(client2);
   
  return clientResults;
 }
 
    public String getMyClient()
    {
     if (myClient ==  null)
     {
      myClient = '<None>';
     }
     return myClient;
    }
    public void setMyClient(String s)
    {
     myClient = s;
    }
    
}


 and here is the page:

 
<apex:page controller="listTestController">

 <apex:sectionHeader title="Client Search" />

 <apex:form>
 
  <apex:pageBlock title="Search Results">
  
   <apex:pageBlockSection title="Clients" columns="1" collapsible="false">
    <apex:pageBlockList value="{!clientResults}" var="client">
     <apex:column>
      <apex:commandButton action="{!selectClient}" value="{!client.Full_Name__c}" rerender="out" status="status">
       <apex:param assignTo="{!myClient}" value="{!client.Full_Name__c}"/>
      </apex:commandButton>
     </apex:column>
     <apex:column value="{!client.Full_Name__c}" headerValue="Name"/>
     <apex:column value="{!client.Address__c}" headerValue="Address"/>
     <apex:column value="{!client.Date_of_Birth__c}" headerValue="Date of Birth"/>
    </apex:pageBlockList>
   </apex:pageBlockSection>
   
  </apex:pageBlock>
  
 </apex:form>
 
 <apex:outputPanel id="out">
  <apex:actionstatus id="status" startText="testing...">
   <apex:facet name="stop">
    <apex:outputPanel>
     <p>Client selected:</p>
     <apex:outputText value="{!myClient}"/>
    </apex:outputPanel>
   </apex:facet>
  </apex:actionstatus>
 </apex:outputPanel>
 
</apex:page>

All appears OK but the param does not seem to assign the value correctly. If I select the first row the output panel updates correctly with "Fred Jones". If I refresh the page and try and select the second row, The value remains as <None>.

I thought initially that the command button or the param was not getting the correct client value but all works with the first row, just not the second.

Any ideas?
 

 

 

 

dchasmandchasman
The problem is the result of a fairly common new-to-VF custom controllers mistake - your getter
getClientResults()
is creating new values every time it gets called and is the root cause of your page's amnesia. For value binding to work properly you need to have your controller maintain some state, e.g. (NOTE I removed the parts that we not relevant to the issue at hand):

public class listTestController {
public Client_Search_Result__c[] getClientResults() {
if (clientResults == null) {
clientResults = new Client_Search_Result__c[]{};

Client_Search_Result__c client1 = new Client_Search_Result__c();
client1.Full_Name__c = 'Fred Jones';
client1.Address__c = '10 Main Street, Auckland';
client1.Date_of_Birth__c = '10/10/1970';
clientResults.add(client1);

Client_Search_Result__c client2 = new Client_Search_Result__c();
client2.Full_Name__c = 'Peter Smashing';
client2.Address__c = '99 Hell Street, Wellington';
client2.Date_of_Birth__c = '10/10/1970';
clientResults.add(client2);
}

return clientResults;
}

private Client_Search_Result__c[] clientResults
}



Message Edited by dchasman on 03-27-2008 08:27 AM
Steve ChadbournSteve Chadbourn
Thanks for the tip Doug. I have updated my controller but the assignTo still does not work.
 
As before, if I select the first item in the list assignTo calls the setter and all works fine. Selecting the second item in the list does not trigger the setter. If I reset the page and select the second item first the setter never gets called. I have inserted debug statements and I can see the setter only getting called if I click the first item.
 
Here is the updated code for anyone who wants to try and replicate this:
 
Controller:
public class paramExampleController
{
 Client_Search_Result__c[] clientResults;
  String myClient;
 
 public PageReference selectClient()
 {
   return null;
 }
 
 public Client_Search_Result__c[] getClientResults()
 {
  if (clientResults == null)
  {
   clientResults = new Client_Search_Result__c[]{};

   Client_Search_Result__c client1 = new Client_Search_Result__c();
   client1.Full_Name__c = 'Fred Jones';
   client1.Address__c = '10 Main Street, Auckland';
   client1.Date_of_Birth__c = '01/01/1960';
   clientResults.add(client1);
   
   Client_Search_Result__c client2 = new Client_Search_Result__c();
   client2.Full_Name__c = 'Peter Smashing';
   client2.Address__c = '666 Hell Street, Wellington';
   client2.Date_of_Birth__c = '02/02/1970';
   clientResults.add(client2);
  }

  return clientResults;
 }
  
 public String getMyClient()
 {
  if (myClient ==  null)
  {
   myClient = '<None>';
  }
  return myClient;
 }
 
 public void setMyClient(String s)
 {
  this.myClient = s;
 }
    
}

 
Page:
<apex:page controller="paramExampleController">

 <apex:sectionHeader title="Client Search" />

  <apex:form>
 
   <apex:pageBlock title="Search Results"> 
  
       <apex:pageBlockSection title="Clients" columns="1" collapsible="false">

        <apex:pageBlockList value="{!clientResults}" var="client">

         <apex:column>
          <apex:commandButton action="{!selectClient}" value="{!client.Full_Name__c}" rerender="out">
              <apex:param assignTo="{!myClient}" value="{!client.Full_Name__c}"/>
             </apex:commandButton>
         </apex:column>
         <apex:column value="{!client.Full_Name__c}" headerValue="Name"/>
         <apex:column value="{!client.Address__c}" headerValue="Address"/>
         <apex:column value="{!client.Date_of_Birth__c}" headerValue="Date of Birth"/>

       </apex:pageBlockList>

   </apex:pageBlockSection>
   
   <apex:pageBlockSection title="Results" columns="1" collapsible="false">
    <apex:outputPanel id="out">
        <p>Client selected:</p>
        <apex:outputText value="{!myClient}"/>
     </apex:outputPanel>
   </apex:pageBlockSection>
  
  </apex:pageBlock>

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

 

GerhardNewman2GerhardNewman2
I have just written some code and discovered that this bug is still here.  It seems to only set the param value on the first row.
Very disappointing that this still has not been fixed.
shivshiv

Hello, can <apex:param> be used to send a value from VF page to Apex class? Is yes how?

If not? how else can it be done?

GerhardNewman2GerhardNewman2
assignTo didn't work, but this does.....
 
 
Code:
        <apex:pageBlockTable value="{!Users}" var="o">
            <apex:column headerValue="{!Role}">
                <apex:commandLink action="{!save}" value="{!o.name}" id="theCommandLink">
                    <apex:param name="personID" value="{!o.id}" />
                </apex:commandLink>
            </apex:column>   
        </apex:pageBlockTable> 

 
using name puts the value into the page parameters which you get back in the controller like this....
 
Code:
    public PageReference save() {                
        String personID = System.currentPageReference().getParameters().get('personID');
    }
 
Good luck!
 
goodankitgoodankit

What is use of <apex:param>