Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

I've been struggling with this for a few days now. I have a Visualforce page that should trigger a search method on the controller. When the method returns the page should render the result. The problem is that although the method is triggered and executes fine the page does not rerender the results. It seems the whichPanelToRender attribute although set to the right value does not maintain the value when the component refreshes. Any suggestions?

This is the page code:

<apex:page controller="PortfolioCatalogController" title="NICE" sidebar="false" showHeader="false" id="NicePortfolioCatalogMain">

    <apex:stylesheet ..."/>

    <apex:includeScript ...}"/>

    <script type="text/javascript">
        $(document).ready(function()
        {
            MainPage.init();
        });
    </script>    

    <div id="headerContainer" class="clearfix">
        <div id="header" class="clearfix">
            ...
        </div>
     </div>

     <div id="pageWrapper" class="clearfix">

        <div id="sideBarCollapsedTrigger"></div>

        <div id="sideBar">
            ...
        </div>

         <apex:form id="theForm">
            <div id="mainContentDiv" class="mainContentDiv_small">                    
                <div id="{!IF(whichPanelToRender == 'MAIN', 'mainContentTop', 'mainContentTop_short')}">
                     <apex:outputPanel id="breadCrumbs" layout="block" rendered="{!whichPanelToRender == 'SEARCH_RESULT'}">
                         <a href="CatalogMain">home</a>search results
                     </apex:outputPanel>
                     <div id="{!IF(whichPanelToRender == 'MAIN', 'searchDiv', 'searchDiv_inner_page')}">
                        <div id="searchContainer">
                            <input class="searchInput" type="text" name="searchField" id="searchField" placeholder="Search" />
                            <input type="image" name="submit" id="searchSubmit" onclick="doSomeSearch();" src="{!URLFOR($Resource.nice_portfolio_catalog)}/images/emptyGif.gif" border="0"/>
                                <apex:actionFunction name="doSomeSearch" action="{!doSearch}" immediate="true" reRender="bottomMiddleSection">                                
                                    <apex:param name="firstParam" assignTo="{!searchTerms}" value=""/>
                                </apex:actionFunction>
                        </div>
                     </div>
                 </div>                                      

                 <div id="mainContentBottom">
                    <apex:outputPanel id="bottomMiddleSection" styleClass="bottomMiddleSection_small">
                        <script type="text/javascript">
                            //for debug
                            alert('{!whichPanelToRender}'); 
                        </script>
                        <apex:outputPanel rendered="{!whichPanelToRender == 'SEARCH_RESULT'}" id="theSearchResultsPanel" layout="block">
                            <table cellpadding="0" cellspacing="0" border="0" width="100%">
                                <tr>
                                    <td height="32"></td>
                                </tr>
                                <tr>
                                    <td width="100%" valign="top">
                                        <div class="pageMainContentContainer">
                                            <h3 class="pageTitle">Search results <span class="searchResultsNumber">({!howManyResults})</span></h3>
                                            <div class="titleUnderline"></div>

                                            <apex:repeat value="{!searchResults}" var="searchResult" id="allSearchResultsRepeat">
                                                <apex:repeat value="{!searchResult}" var="objectSearchResult" id="objectSearchResultsRepeat">                                                    
                                                    <apex:dataList value="{!objectSearchResult}" var="singleSearchResult" id="singleSearchResultsRepeat">
                                                        <apex:outputLink value="{!singleSearchResult.Name}" id="aSearchResultName" styleClass="searchItemIL_title solution_ItemBullet">{!singleSearchResult.Name}</apex:outputLink>                     
                                                        <apex:outputText value="{!singleSearchResult.Description__c}" id="aSearchResultContent" styleClass="searchItemContent"/>                     
                                                    </apex:dataList>
                                                </apex:repeat>
                                            </apex:repeat>                 
                                        </div>
                                    </td>
                                </tr>
                            </table>                        
                        </apex:outputPanel>

                        <apex:outputPanel rendered="{!whichPanelToRender == 'MAIN'}" id="theMainPanel" layout="block">
                            <table cellpadding="0" cellspacing="0" border="0">

                            </table>
                        </apex:outputPanel>
                    </apex:outputPanel>
                    <div id="bottomRightSection">
                        <a href="#"><apex:image url="{!URLFOR($Resource.nice_portfolio_catalog, 'images/marketingBanner.jpg')}"/></a>
                    </div>
                </div>
            </div><!--mainContentDiv-->
        </apex:form>
    </div><!--pageWrapper-->
</apex:page>  

This is the controller:

public class PortfolioCatalogController{

    private final Portfolio_Catalog_Item__c catalogItem;
    private transient static String basicInfoFields = 'Id, Name';
    private transient static String Portfolio_Catalog_Item_extendedInfoFields = 'Id, Name, Full_Name__c, Item_Type__c, Value_Proposition__c, Parent_Item__c, Containing_Catalog_Item__c, Buyer__c, Base_Pricing_Model__c';

    public PortfolioCatalogController(){
        howManyItemsInSection = 5;
        whichPanelToRender = PanelNames.MAIN.Name();
    }

    public enum PanelNames {MAIN, SEARCH_RESULT}

    public String whichPanelToRender{get;set;}

    public ID catalogItemId{get;set;}

    public integer howManyItemsInSection{get;set;}

    public String searchTerms{get;set;}

    public List<List<Portfolio_Catalog_Item__c>> searchResults{get;set;}

    public integer howManyResults{
        get{
            if(searchResults == null)
                return 0;
            return searchResults.size();
        }
        set;
    }

    public PageReference doSearch(){

        String searchTerm = 'product';//hard coded for clarity
        whichPanelToRender = PanelNames.SEARCH_RESULT.Name();

        if(searchTerm == null || String.isBlank(searchTerm)){
            system.debug(LoggingLevel.WARN, 'search terms is blank');    
        }

        String[] searchTermList = String.escapeSingleQuotes(searchTerm).split(' ');

        for(integer i = 0; i < searchTermList.size(); i++){
            searchTermList[i] = searchTermList[i].deleteWhitespace();
            if(searchTermList[i].isWhitespace())
                searchTermList.remove(i);
        }

        String findSearchQuery = '';
        //create SOSL FIND string from search terms
        for(integer i = 0; i < searchTermList.size(); i++){
            findSearchQuery += searchTermList[i];
            if(i != searchTermList.size() -1)
                findSearchQuery += ' OR ';
        }

        String queryString =  'FIND \'' + findSearchQuery + '\' IN ALL FIELDS RETURNING Portfolio_Catalog_Item__c(id, Name, Value_Proposition__c, Description__c)';
        System.debug(LoggingLevel.DEBUG, queryString);

        try{
            searchResults = search.query(queryString);//List<List<Portfolio_Catalog_Item__c>>     
        }
        catch(Exception e){
            System.debug(LoggingLevel.WARN, e);
            //return new List<List<Portfolio_Catalog_Item__c>>();
        }
        return null;
    }
}
share|improve this question
1  
Not enough code. Please provide searchDivand searchDiv_inner_page. Why do you have a plain html <div id="bottomMiddleSection">? –  mast0r Dec 17 '12 at 20:55
    
I started with a static html I got from the designer and had to apply it to my VF page. So I only changed/added VF components where I needed –  Dedo Dec 18 '12 at 8:43
add comment

4 Answers

I think you are supposed to re-render theSearchResultsPanel and not the div id bottomMiddleSection. Apex usually re-renders only apex components and not the html ones. The rendering condition will be checked on re-rendering.

share|improve this answer
    
I've tried but it doesn't work as well. When I look at the value of whichPanelToRender in the page I see that it has not changed. For some reason the value is reset to its original value. Maybe it is a viewstate issue? –  Dedo Dec 19 '12 at 14:02
    
Did you debug just before returning NULL? Also, why don't you use simple getter and setter like this. public String whichPanelToRender{get;set;}. I couldn't understand what you are doing in your setter. –  Vignesh Dec 20 '12 at 2:13
    
For debugging purposes there is also a system.debug line in the setter which I removed from the code snippet for clarity –  Dedo Dec 20 '12 at 10:27
    
When I debug I see two logs are generated: the first is for the action call triggered by me clicking the search button and a second log which is for a controller initialization. I think this is the root cause - for some reason after I set whichPanelToRender to the desired value a new controller is being created with the default value, and this is what I'm seeing in the page. Can anyone help me understand why a new controller is initialized? –  Dedo Dec 20 '12 at 12:34
    
@Harniv : Yeah! That happens sometimes but I'm not sure why the constructor is re-initialized. It would be better if you can post litte more detailed code. –  Vignesh Dec 21 '12 at 4:48
show 2 more comments

This could be due to the fact that your outputpanel isn't initially rendered, and when you try to rerender it later on, the outputpanel (in reality a div) doesn't exist in the dom, and the component cannot be found for a rerender.

what you could do is: put your outputpanel in another outputpanel, and have the outer outputpanel initially rendered, and apply your rerender to that panel

share|improve this answer
    
If that makes sense? :) –  PJC Dec 17 '12 at 20:44
    
That does make sense, but I think some code would help explain the concept! –  metadaddy Dec 17 '12 at 20:51
    
I dont think this is a problem here. Because he reRender NOT a theSearchResultsPanel directly. –  mast0r Dec 17 '12 at 20:57
    
If I print out the value of the whichPanelToRender attribute I see it is not what I expect so my guess was that there is something wrong with the controller that does not retain the value. If I set this value in the constructor (just for testing) the pages reads it well, so I was thinking that after the search action a new controller instance is being created and assigned to the page but that doesn't make any sense. - Any suggestions? –  Dedo Dec 18 '12 at 8:47
add comment

Change the divs that are getting rerendered to apex:outputPanels. There is no attribute of div called rerender. The rerender is an attribute of some of the Visualforce components.

Change

<div id="bottomMiddleSection">

    ....content....
</div>

to

<apex:outputPanel layout="block" id="bottomMiddleSection">

  ....content....
</apex:outputPanel>

Check out the apex:outputPanel documentation. When you specify layout="block" Visualforce generates a div.

Check out the apex:commandButton documentation, specifically the rerender attribute documentation.

The ID of one or more components that are redrawn when the result of an AJAX update request returns to the client. This value can be a single ID, a comma-separated list of IDs, or a merge field expression for a list or collection of IDs.

An HTML div tag is not a Visualforce component.

share|improve this answer
    
I've fixed that but it is still not working. You can see my updated code in the revised question. Thanks –  Dedo Dec 23 '12 at 15:15
add comment

I think that

<div id="{!IF(whichPanelToRender == 'MAIN', 'mainContentTop', 'mainContentTop_short')}">

is outside all rerender regions, so is never evaluated more than once ( frist page load)

I often get stuck debugging rerender issues and my current strategy is to rerender the top-most form "theForm" from everywhere on the page, then verify all functionality is correct, and only then will i attempt to re-render individual sections.

Optimize last, imho.

share|improve this answer
    
Good approach - but using the code in the embedded JS alert('{!whichPanelToRender}'); I can see the my value is always MAIN and I cannot find out why. –  Dedo Dec 23 '12 at 23:07
    
When you use immediate="true", you are asking the controller to skip validation rules and don't bind any of my variables on this page, just call the function. Not sure this is the cause of your rerender issue but i would try to remove this and see if it helps. Also, i would add a message to the page in your exception handler to see if this is throwing anything that you can't see. When you do this, you should add <apex:pageMessage /> so that you can see the issue, this needs to be inside a rerender also, i suggest you rerender the entire form –  VNE_Hess Jan 3 '13 at 2:24
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.