+ Start a Discussion
neckrneckr 

How I do use the assign to attribute in the param component to pass value for query filter

Hi,  I am a bit stuck trying to figure out how to properly use the assign to attribute in the param component.

 

I am trying to display a list of categories (using command link component) .  Based on the category the user selects in the list , I want to filter out the services and display the filtered list below on the same page.

 

Here is the controller:

 

 

public with sharing class wrapperClassController {


public String category {get; set;}


public pagereference viewST(){
return NULL;
}


//This query displays my categories
public List<Service_Categories__c> getCategories(){
return [SELECT Name FROM Service_Categories__c WHERE Service_Name__c = 'NULL'];

}

public List<aServiceTask> servicetaskList {get; set;}

// This query displays my services - however nothing is returned since I beleive my category variable is not being assigned properly throughout the process .
public List<aServiceTask> getServiceTasks() {
if(servicetaskList == null) {
servicetaskList = new List<aServiceTask>();
for(Service_Categories__c a: [select Id, Name, Service_Name__c from Service_Categories__c where Name = :category AND Service_Name__c <>'NULL']) {

servicetaskList.add(new aServiceTask(a));
}
}
return servicetaskList;

}


}

 

 

Here is the Page:

 

 

<apex:page controller="wrapperClassController">

<apex:form >
<apex:pageBlock >
<apex:pageBlockSection title="Work Categories">

<apex:dataList value="{!Categories}" var="c" id="table" type="none" >
<apex:commandLink value="{!c.Name}" action="{!ViewST}" >
<apex:param value="{!c.Name}" assignTo="{!category}"/>

</apex:commandlink>

</apex:dataList>

</apex:pageBlockSection>

<apex:pageBlockSection title="Service Tasks">

<apex:commandButton value="Process Selected" action="{!processSelected}" rerender="table"/>
<apex:outputText value="{!category}"/>
<apex:pageBlockTable value="{!servicetasks}" var="a" id="table">
<apex:column >
<apex:inputCheckbox value="{!a.selected}"/>
</apex:column>
<apex:column value="{!a.ST.Service_Name__c}" />
</apex:pageBlockTable>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>
</apex:page>

 

Thank you in advance!

 

Best Answer chosen by Admin (Salesforce Developers) 
Bhawani SharmaBhawani Sharma

You only need to define name for your <apex:param component:

 

<apex:commandLink value="{!c.Name}" action="{!ViewST}" rerender="pb">
    <apex:param name="param1" value="{!c.Name}" assignTo="{!category}"/>
</apex:commandlink> 

 

Rest is ok.

All Answers

bob_buzzardbob_buzzard

In my experience, params don't get sent back to the controller unless you add a rerender attribute to the command link.

 

Try:

 

 

<apex:form >
       <apex:pageBlock id="pb">
          <apex:pageBlockSection title="Work Categories">
                 
                  <apex:dataList value="{!Categories}" var="c" id="table" type="none" >
                      <apex:commandLink value="{!c.Name}" action="{!ViewST}" rerender="pb">
                          <apex:param value="{!c.Name}" assignTo="{!category}"/>
                      </apex:commandlink>   
                  </apex:dataList>
                  
         </apex:pageBlockSection>

 

 

neckrneckr

Thanks for your reply.  Made the changes you suggested, I added the id to the page block and added the rerender attribute to the command link on the page.  Still not working.

 

Is there something more I need to do inthe viewST Method?


public pagereference viewST(){
return NULL;
}

bob_buzzardbob_buzzard
Hmmm. You shouldn't need to do anything else. Have you tried adding some debug to this method to dump out the value of the category property?
neckrneckr

I thought about that and I tried to do setup some outputs in my code following some examples and had no luck. I have not done that before and I think my knowledge of the sequence of order APEX executes may restrict proper logic for this.  Can you provide me some sample code I can use to debug my problem?

Bhawani SharmaBhawani Sharma

You only need to define name for your <apex:param component:

 

<apex:commandLink value="{!c.Name}" action="{!ViewST}" rerender="pb">
    <apex:param name="param1" value="{!c.Name}" assignTo="{!category}"/>
</apex:commandlink> 

 

Rest is ok.

This was selected as the best answer
neckrneckr

Thank you, this made some progress.  The category variable is now being assigned as I tested with an output field.  However my List of Service tasks which is called by the {!servicetask} method in the page is not rerendering with the new filtered list based on the category variable. If I hard code any category, the filtered list is displayed on page load, so its not my query.

 

Can't seem to understand why the filtered list doesn't show on the rerender? Anything I am missing from this perspective.

 

Thanks,

 

Ricky

bob_buzzardbob_buzzard

This is because you are caching the query results in the following method:

 

 

public List<aServiceTask> getServiceTasks() 
{
    if(servicetaskList == null) 
    {
       servicetaskList = new List<aServiceTask>();
       for(Service_Categories__c a: [select Id, Name, Service_Name__c from Service_Categories__c where Name = :category AND Service_Name__c <>'NULL']) 
       {
    
          servicetaskList.add(new aServiceTask(a));
       }
    }

    return servicetaskList;
}
  

 

If you clear it down in your action method that should do the trick:

 

 

public pagereference viewST()
{
   // null the service task list to force recreate
   servicetaskList=null;

   return NULL;
}

 

 

 

 

Bhawani SharmaBhawani Sharma

 

public List<aServiceTask> servicetaskList
	{
		get
			{
				servicetaskList = new List<aServiceTask>();
				for(Service_Categories__c a: [select Id, Name, Service_Name__c from Service_Categories__c where Name = :category AND Service_Name__c <>'NULL'])
					{
						servicetaskList.add(new aServiceTask(a));
					}
				return servicetaskList;
			}
	}

 I would recommand for this approach as this will always get the refreshed data from the database.

 

 

 

bob_buzzardbob_buzzard

The downside to doing it this way (and I've done it myself plenty of times in the past) is that getters may be called multiple times when the page is rendering, which means that the SOQL query will be run multiple times, potentially impacting performance.  The Visualforce Developer's Guide specifically recommends against this in the Best Practices section, under Load Times:

 

--- snip ---

 

 

Load Times
In order for your Visualforce page to be accessible, your page size must be under 15 MB. A larger page size directly
affects load times.To improve Visualforce page load times:
• Cache any data that is frequently accessed, such as icon graphics
Avoid SOQL queries in your Apex controller getter methods

 

--- snip ---

 

 

Bhawani SharmaBhawani Sharma

The reason why I want to go with this, while playing on the page some other users added records in the database.

If I have getter SOQL then I can get the refreshed records on the page as soon as rerender happen.

 

I know It will be queried each time but still you will get the real time data.

bob_buzzardbob_buzzard

But if you have an actionmethod that is nulling the cached list, then the latest records will be retrieved when the rerender happens anyway.  

Bhawani SharmaBhawani Sharma

but the latest  data will not be displayed untill the actionmethod is called, while section displaying the list is rerendering.

 

But having SOQL in getter will work independently. Latest will be displayed as soon as section's rerender happens. 

 

bob_buzzardbob_buzzard

When the user clicks the button, the action method is invoked, which in my suggested solution nulls the cached list.  When the action method completes, the page is recreated, and the first call to the getter recreates the cached list with the new values.  Once the action method has completed, the rerender takes place.

 

The rerender doesn't happen independently of the action method, it happens as a direct result of it completing. If you are referring to the rerender that takes place as part of the processSelected action method, again it would be better to null the cached list in processSelected than have SOQL in the getter method.

 

According to the Visualforce Developer's Guide, getters can be called multiple times when a page is generated, and if there is SOQL in the getter then a round trip to the database is required each time.

 

Generally speaking, if the docs mention it as a Best Practice, it means there are real benefits to working that way.

 

We are starting to hijack this thread now - we've given the OP a couple of options here so I'd suggest we leave it at that.  I'm happy to discuss this further in a private message exchange.

Bhawani SharmaBhawani Sharma

Thanks Bob,

 

You are the expert, you know better and having good experience than me. I just wanted to share what are the troubles I have faced in past.

Got a chance to learn some good things with this thread :smileyvery-happy:

neckrneckr

Bob, this approach you provided renders my list - Thank you!

 

Last quick question for this stage of the code.  Pretty basic, but couldnt find an example anywhere. How do I set the category varible with a default value on the first load of the page.  What  syntax and where is the best place to put it?

See below for what I am thinking.

 

Public String category {get; set;}

// set category default value to value of account.Con_Work_Category__c --

 

category = account.Con_Work_Category__c;

//category = 'Roofing'; // For testing use static value what syntax and where?

bob_buzzardbob_buzzard

There's a few ways to do this - here's three

 

(1) Add a check to the getter to set a value if it is null

(2) Initialize it in an anonymous block after the declaration

(3) Initialise in the constructor

 

I usually initialise in the constructor.  It really depends on where your initial value is coming from:

 

 

// constructor
public WrapperClassController()
{
    category='Roofing';
}

 

 

neckrneckr

Choose method 1 and works great!

 

Thanks Again!!!!!

bob_buzzardbob_buzzard

Excellent.  Glad to hear it.

 

@techforce - I've just reread my earlier post and it comes across as more of a lecture than I'd planned.  Sorry about that, I wasn't intending to be quite so forceful about it.

neckrneckr

I attempted to assign the initial value to my variable and I receive the following error: System.NullPointerException: Attempt to de-reference a null object
Class.ConAcctWorkCoverageControllerExtension: line 23, column 13 External entry point.

 

Is there something I am missing in the syntax?

 

 

public with sharing class ConAcctWorkCoverageControllerExtension {

Private final Account acct;
    public ConAcctWorkCoverageControllerExtension(ApexPages.StandardController stdcontroller) {
    this.acct = (Account) stdcontroller.getRecord();
    }
//**********************************************************VARIABLE DECLARATION**************************************************************************

//Category Variables------------------------------------------------------
Public String category {get; set;} 
{category = Account.Con_Work_Category__c ;}

 

 

I tried declaring the value in the following method and it doesnt give me an error, however I need to initialize on page load as the variable is used in a query search to populate a datatable.

 

 

public Account getacct() {  
//category = acct.Con_Work_Category__c ;
servicetaskList = NULL;
return acct;  
}

 

 

Bhawani SharmaBhawani Sharma

Why don't you initialize your variable in constructor part ? May be this will help.

neckrneckr

I tired to initialize in the constructor using this syntax:

 

{category = Account.Con_Work_Category__c ;}

 

but it is giving me an external entry point error.  Is there a special syntax to refernece the account object field outside of a get method?

Bhawani SharmaBhawani Sharma

category = this.acct.Con_Work_Category__c;

 

If this doesn't help please post your code here, That can give a better idea to me.

neckrneckr

it worked thanks!

Bhawani SharmaBhawani Sharma

Can you mark it accepted if it solved ypur problem?  This will help others to get rid from same kind of issue.