function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
OldDeadBugOldDeadBug 

Rendering different tables based on a picklist value still not working

It seems like I've read several solutions to this, none of which appear to work for me

 

I have a page that will have two tables. WHich one is rendered depends on a picklist option in a selectList.

 

Relevant Apex Code:

 

public string LineType;

public string getLineType()    // This is the selectOption value from the selectList
    {
        return LineType;
    }
    public void setLineType(string LT)
    {
        this.LineType = LT;
    }


    public list<OpportunityLineItem> LineItems;
    
    public list<OpportunityLineItem> getLineItems()  // for the Opp Line Item table
    {
        
        LineItems = [SELECT id, TotalPrice, PriceBookEntry.Product2.Name, Opportunity.Name
                     FROM OpportunityLineItem
                     WHERE OpportunityID = :ApexPages.currentPage().getParameters().get('Id')];
        return LineItems;
    }
    
    public list<QuoteLineItem> QuoteLines;
    
    public list<QuoteLineItem> getQuoteLines()     // for the Quote Line Item Table
    {
        QuoteLines = [SELECT id, Quantity, UnitPrice, PriceBookEntry.Product2.Name 
                      FROM QuoteLineItem
                      WHERE Quote.OpportunityId = :Opp.Id];
        return QuoteLines;
    }

 

 

And the Apex Code

 

<apex:page standardcontroller="Opportunity" extensions="QOA_ManageQuotesController" >
<h1> Manage Quotes for {!Opportunity.Name} </h1>
<apex:form >

<apex:pageBlock id="LineItemsTable">
<h1> Select Line Type </h1>
<apex:selectList id="TableSelect" value="{!LineType}" size="1" >
<apex:selectOption itemValue="Products" itemLabel="Products"/>
<apex:selectOption itemValue="QOA" itemLabel="QOA"/>
<apex:selectOption itemValue="SFDC Lite" itemLabel="SFDC Lite"/>
</apex:selectList>



<apex:pageBlockTable id="Table" value="{!LineItems}" var="item" columns="6" rendered="{!LineType == 'Products'}" >
<apex:column headervalue="Products">
<apex:outputLink value="/{!item.id}" id="theLink">{!item.PriceBookEntry.Product2.Name}</apex:outputLink>
</apex:column>
<apex:column value="{!item.TotalPrice}"/>
<apex:column headerValue="Create" width="5%">
<apex:commandButton action="{!CreateQuote}"/ value="Create Quote">
</apex:column>
<apex:column headerValue="View" width="5%">
<apex:commandButton action="{!ViewQuote}"/ value="View Quote">
</apex:column>
<apex:column headerValue="Refresh" width="5%">
<apex:commandButton action="{!RefreshQuote}"/ value="Refresh Quote">
</apex:column>
<apex:column headerValue="Delete" width="5%">
<apex:commandButton action="{!DeleteQuote}"/ value="Delete Quote">
</apex:column>
</apex:pageBlockTable>


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

 

 

The results of this is that the table is not rendered when the Products value is selected.

 

If I remove the 'rendered="{!LineType =='Products'}"' attribute, the LineItems page renders as expected. I've tried using

{!IF(LineType = 'Products', true, false)}, which doesn't work, although both

 

rendered="{!LineType != 'Products'}" and {!IF(LineType = 'Products', false, true)} works just fine, except its wrong.

 

Clearly the LineType value isn't being set, or else the Table component isn't seeing it. Can someone tell me where I'm going wrong here??

Best Answer chosen by Admin (Salesforce Developers) 
AvromAvrom

1. The rule is that you shouldn't have both a rerender target and a nontrivial "rendered" attribute on the *same* tag. You can certainly use both, but the "rendered" tag should always be in a component *inside* a container that is the rerender target. The reason for this is that, in order to do a partial page refresh, your browser needs to be able to find a DOM element with the same client ID as your rerender target. If that rerender target has rendered evaluated to false, it will never be generated to the DOM in the first place, so there will be no corresponding client ID. If an AJAX request later changes the rendered value to true, rerender will fail when your browser tries to find the appropriate DOM element.

 

2. That attribute value is case sensitive. Have you actually tried "onchange", rather than "onChange"? Your sample code works for me if I make that replacement.

All Answers

AvromAvrom

I don't see anything that posts the value of your select list back to the server. "rendered" is a server-side attribute, meaning that things your user does in the browser can't change its value unless they're posted back.

 

The most obvious possibility would be to use an <apex:actionSupport> tag inside your select list.

 

By the way, if you decide to use AJAX rerendering (using a rerender attribute on your actionSupport tag), you never want to make the target of the rerendering a component with a dynamic "rendered" attribute. Instead, use an outputPanel around the component, and rerender that:

 

 

<apex:selectList id="TableSelect" value="{!LineType}" size="1" >
  ...
  <apex:actionSupport event="onselect" rerender="Panel" />
</apex:selectList>
...
<apex:outputPanel id="Panel">
  <apex:pageBlockTable id="Table" value="{!LineItems}"  var="item" columns="6" rendered="{!LineType == 'Products'}" >
...
  </apex:pageBlockTable>
</apex:outputPanel>

 

 

OldDeadBugOldDeadBug

Thanks for the response

 

I'm getting an error for the 'action=""' attribute on the actionSupport. I'm not sure what I should add here. Do I need to add a method to the controller that somehow sends the the picklist selection to the server??

AvromAvrom

Sorry, you must have seen my post before I edited it. No, your value will automatically be sent to the server; an action value is only necessary if you need to do something additional. No action attribute is necessary here at all.

OldDeadBugOldDeadBug

I added the event="onselect" to the actionsupport. I've wrapped the pageBlockTable into an outputPanel,

 

However, my debug log tells me that the LineType value is still null. So, apparently the picklist selection is not being sent to the server.

 

The table is rendering, but it was already rendering before I added the actionSupport to the SelectList. The problem is that I want to render a different table when selecting a different picklist value, such as:

 

<apex:pageBlockTable id="ProductsTable" value="{!IF(LineType == 'Products' , LineItems, QuoteLines)}"  var="item"  >

 

The line above throws an error that its missing a ')' - although I have no idea where its missing. But that's not the issue.

 

(Ultimately I will use logic in the controller to select which list to display, but it still needs to be based on the selection of the picklist)

 

Here's the corrected selectList:

 

 

<apex:pageBlock id="LineItemsTable">
       <h1> Select Line Type </h1>
        <apex:selectList id="TableSelect" value="{!LineType}" size="1">
            <apex:selectOption itemValue="Products" itemLabel="Products"/>
            <apex:selectOption itemValue="QOA" itemLabel="QOA"/>
            <apex:selectOption itemValue="SFDC Quotes" itemLabel="SFDC Quotes"/>
            <apex:actionSupport event="onselect" rerender="Panel" />

        </apex:selectList>

 

When the page renders, the list defaults to Products, and the table appears. However, the debug log tells me that LineType is actually null when the page loads, and nothing reRenders if I change the value. Since the Linetype value is null, its not available as a criteria for anything.

 

 

Here again is the controller code for the LineType

 

 

    public string LineType;
    
    public string getLineType()
    {
        system.debug('LineType is '+LineType);
        return LineType;
       
    }
    public void setLineType(string LT)
    {
        this.LineType = LT;
    }

 So, I have a getter and setter for LineType, I have a SelectList with an actionSupport with event="onselect". ReRender is set, but again, the problem is not the table rendering, but that the event="onselect" isn't sending the picklist value to the LineType setter. In fact, after adding debug statements in the setter code, it appears that the setter isn't being called at all upon selecting a value.

 

Why?

 

I have also taken the step of setting the LineType value in the constructor 'LineType = 'SFDC Quote';', which does show up in the debug log, but changing the value of the picklist doesn't change the value of the variable.

 

If I can get that to work, I should be able to get the rest of what I'm after to work. It seems like it should be a simple answer for which I will be kicking myself once its pointed out.

 

d3developerd3developer

I've used "onchange" instead of "onselect" successfully, although I think you also use "onblur."

 

Btw, I think you want this for your PageBlockTable(s):

 

<apex:outputPanel id="regionToReRender">
<apex:pageBlockTable id="Table" value="{!LineItems}" var="i" rendered="{!LineType == 'Products'}" >
...
</apex:pageBlockTable>
<apex:pageBlockTable id="PrTable value="{!QuoteLines}" var="i" rendered="{!LineType == 'Quotelines'}" >
...
</apex:pageBlockTable>


 

 

OldDeadBugOldDeadBug

Couple of ?s here:

 

1) I was told earlier and have read in other posts that if I am reRendering, that I should not use the Rendered attribute, although no one specified if the Rendered attribute on the pageBlocktable is still usable if the table is wrapped in a reRenderable outputPanel. My understanding of the comments that you can only use one or the other. Somone please clarify.

 

2) I tried a simpler example to just get a reliable result:

 

 

<apex:panelGrid columns="3" id="searchGrid">
      <h1> Search QPricer &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </h1>
      <apex:selectList id="chooseSearchType" value="{!searchType}" size="1">
          <apex:selectOption itemValue="CU_ID" itemLabel="CUID"/>
          <apex:selectOption itemValue="SalesRep_ID" itemLabel="SalesRep ID"/>
          <apex:actionSupport event="onChange" reRender="Panel"/>
      </apex:selectList>
      <apex:inputText value="{!searchValue}" id="searchValue"/>
</apex:panelGrid>


<apex:outputpanel id="Panel">   
      <apex:outputText value="{!searchType}"/>
</apex:outputpanel>

 

 

Now, when I select a searchType option, I would expect the value string of that option to be returned to the Panel. In fact, nothing happens at all, regardless of whether I use 'onchange', 'onselect', or anything else. I don't even get the outputPanel or the text. This is wrapped in a form tag, so that's not the problem.

 

A similar question had a solution where the actionSupport tag had to be wrapped in an actionRegion tag. I haven't tried that yet, but it seems like a lot of tags just to get a term from the page in to the controller and back again.

 

Can someone provide a simple example of using the actionSupport in a SelectList that actually works?? I've looked at the examples in the guide, but the SelectOption examples don't have an actionSupport component, and the actionSupport component example doesn't use the selectOptions. The 'Click Me' counter worked, but its not a selectOption component.

 

 

 

 

AvromAvrom

1. The rule is that you shouldn't have both a rerender target and a nontrivial "rendered" attribute on the *same* tag. You can certainly use both, but the "rendered" tag should always be in a component *inside* a container that is the rerender target. The reason for this is that, in order to do a partial page refresh, your browser needs to be able to find a DOM element with the same client ID as your rerender target. If that rerender target has rendered evaluated to false, it will never be generated to the DOM in the first place, so there will be no corresponding client ID. If an AJAX request later changes the rendered value to true, rerender will fail when your browser tries to find the appropriate DOM element.

 

2. That attribute value is case sensitive. Have you actually tried "onchange", rather than "onChange"? Your sample code works for me if I make that replacement.

This was selected as the best answer
OldDeadBugOldDeadBug

Thanks for clarifying #1

 

#2) Thanks for reminding me about the case-sensitivity of AJAX calls, I'm pretty sure that was it.

 

I'm now off to pound my head into the wall,