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
John L.John L. 

Multi-instance pick-lists in a PageBlockTable

I've been asked to post this question here, as it may be a more appropriate venue than the Apex Code Development Discussion Board, where it originally appeared. Pardon the duplication is you're a regular reader of both boards.

 

I'm having trouble retrieving the value of pick-lists, one per line-item, in a PageBlockTable.

I have been able to display the lists, which then also correctly display the appropriate values from the database.

 

The user documentation seems vague in this area, specifically in locating any user modifications. My best guess is via a reference such as:

 

Page.pagename.ulist.users.level.ulvl.getValue() , where "ulist" is the id of the PageBlock, "users" is the id of the PageBlockTable,  "level" is the id of the SelectList, and "ulvl" is the id of the SelectOptions tag. Admittedly, there is no line-item selector in this best guess, and the Apex compiler indicates I have guessed incorrectly.

 

I had thought the in-storage attribute would be updated (the data from the original SOQL Select that determined the initial value), however that was not the case.

 

Thanks in advance for any help you may be able to provide. 

Best Answer chosen by Admin (Salesforce Developers) 
Ron HessRon Hess

looks like you were using two seperate forms, they each have seperate view-states, so changes made in one were not visible in the other form on that same page.

 

generaly, except in rare and unknown cases, you should use one apex form per page. If you check out the page, each and every form will have a complete duplicate of the viewstate, thus being slow and larger than needed.

 

so, the working sample i built looks like this :

 

 

<apex:page controller="multiPick"><apex:form > <apex:pageBlock id="list" title="Page Block Title"> <apex:pageBlockButtons location="bottom"> <apex:commandButton action="{!save}" value="Save"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </apex:pageBlockButtons> <apex:pageBlockTable id="table" value="{!tbl}" var="item"> <apex:column headervalue="Level" > <apex:selectList id="level" value="{!item.rating}" multiselect="false" size="1"> <apex:selectOptions id="alvl" value="{!olvl}"/> </apex:selectList> </apex:column> <apex:column headervalue="rating" value="{!item.rating}"/> <apex:column headervalue="Attribute 1" value="{!item.name}"/> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>

 

 and

 

public class multiPick { public List<SelectOption> olvl = new List<SelectOption>(); List<Account> lo = new List<Account>(); public List<Account> getTbl() { try { lo = [ SELECT name,rating FROM account limit 3 ]; olvl = getLevels(); } catch( Exception E ) { ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.FATAL, 'Controller failed with exception '+E); ApexPages.addMessage(myMsg); lo = null; } return lo; } public List<SelectOption> getLevels() { List<SelectOption> options = new List<SelectOption>(); options.add(new SelectOption('Option 1','Option 1')); options.add(new SelectOption('Option 2','Option 2')); options.add(new SelectOption('Option 3','Option 3')); return options; } public List<SelectOption> getolvl() { return olvl; } public PageReference save() { for(Account o: lo){ update o; System.debug('Updated Object='+o); } return null; } }

 

 enjoy!

 

 

All Answers

Ron HessRon Hess

In your visualforce page do you use <apex inputField > for the picklists ?

 

or do you construct the list of selectoptions in Apex and then expose that on the visualforce page ?

John L.John L.

A list of SelectOptions.

 

The methodology correctly displays the current value for each pick-list. I'm having trouble retrieving user input and updating the database from an Apex method, invoked via button press, after modifying the pick-list.

Ron HessRon Hess

The value attribute of the SelectList is modified when the user modifies it in the UI

 

so what ever expression you are using to set the value, already has the changed value. 

 

try out the SelectList sample in the doc to see how data binding between the value expression and the controller is done.

John L.John L.

My experience is that this binding is not occuring in the User Interface. If I had developed the UI, I wouldn't have to even create the List<SelectOptions> in Apex code for a object attribute of type pick-list. For this reaason I suspect that the binding of the user interactive choice is not occuring correctly. There is additional evidence in the fact that the UI design does not account for the possibility/retrieval of the iteration value.

 

As I said previously, I generate a List<Object> via SOQL SELECT, and the pick-list attribute current values are reflected "out" to the UI display, but the user interactive choice(s) are not returned "into" the corresponding List<Object> entries.

 

Could someone attempt to create this UI case themselves, and validate that is does not operate correctly? (or get it to work, and tell me how you did it?)

 

Thanks again for your support and consideration.

Ron HessRon Hess

 i'd have to see a sample of what you are doing.

 

 

here is a list of picklists demoooo

 

 

You can edit a set of records using list controllers, too. For example, if you create a page with the following markup: <apex:page standardController="Opportunity" recordSetVar="opportunities" tabStyle="Opportunity" sidebar="false"> <apex:form > <apex:pageBlock > <apex:pageMessages /> <apex:pageBlockButtons > <apex:commandButton value="Save" action="{!save}"/> </apex:pageBlockButtons> <apex:pageBlockTable value="{!opportunities}" var="opp"> <apex:column value="{!opp.name}"/> <apex:column headerValue="Stage"> <apex:inputField value="{!opp.stageName}"/> </apex:column> <apex:column headerValue="Close Date"> <apex:inputField value="{!opp.closeDate}"/> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>

 

 

 

John L.John L.

Apex Tags: ---------- <apex:page> <apex:pageBlock id="list" title="Page Block Title"> <apex:pageBlockButtons location="bottom"> <apex:form > <apex:commandButton action="{!save}" value="Save"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </apex:form> </apex:pageBlockButtons> <apex:pageBlockTable id="table" value="{!tbl}" var="item"> <apex:column headervalue="Level" > <apex:form > <apex:selectList id="level" value="{!item.EHT_Level__c}" multiselect="false" size="1"> <apex:selectOptions id="alvl" value="{!olvl}"/> </apex:selectList> </apex:form> </apex:column> <apex:column headervalue="Attribute 1" value="{!item.attr1}"/> <apex:column headervalue="Attribute 2" value="{!item.attr2}"/> <apex:column headervalue="Attribute 3" value="{!item.attr3}"/> </apex:pageBlockTable> </apex:pageBlock> </apex:page> Apex Code (non-pertinent portions removed) ------------------------------------------ public List<SelectOption> olvl = new List<SelectOption>(); List<Object> lo = new List<Object>(); public List<Object> getTbl() { try { lo = [ SELECT attr1,attr2,attr3,EHT_Level__c,Department FROM Object ]; olvl = getLevels(); } catch( Exception E ) { ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.FATAL, 'Controller failed with exception '+E); ApexPages.addMessage(myMsg); lo = null; } return lo; } public List<SelectOption> getLevels() { List<SelectOption> options = new List<SelectOption>(); options.add(new SelectOption('Option 1','Option 1'); options.add(new SelectOption('Option 2','Option 2'); options.add(new SelectOption('Option 3','Option 3'); return options; } public List<SelectOption> getolvl() { return olvl; } public PageReference save() { for(Object o: lo){ update o; /* Updated selection(s) from pick-list(s) have not been populated here, and do not appear in database as a result */ System.debug('Updated Object='+o); } return null; }

 

I think I've accurately represented the spirit of the problem I'm having.

 

Thanks in advance for any help you can provide.

Ron HessRon Hess

looks like you were using two seperate forms, they each have seperate view-states, so changes made in one were not visible in the other form on that same page.

 

generaly, except in rare and unknown cases, you should use one apex form per page. If you check out the page, each and every form will have a complete duplicate of the viewstate, thus being slow and larger than needed.

 

so, the working sample i built looks like this :

 

 

<apex:page controller="multiPick"><apex:form > <apex:pageBlock id="list" title="Page Block Title"> <apex:pageBlockButtons location="bottom"> <apex:commandButton action="{!save}" value="Save"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </apex:pageBlockButtons> <apex:pageBlockTable id="table" value="{!tbl}" var="item"> <apex:column headervalue="Level" > <apex:selectList id="level" value="{!item.rating}" multiselect="false" size="1"> <apex:selectOptions id="alvl" value="{!olvl}"/> </apex:selectList> </apex:column> <apex:column headervalue="rating" value="{!item.rating}"/> <apex:column headervalue="Attribute 1" value="{!item.name}"/> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>

 

 and

 

public class multiPick { public List<SelectOption> olvl = new List<SelectOption>(); List<Account> lo = new List<Account>(); public List<Account> getTbl() { try { lo = [ SELECT name,rating FROM account limit 3 ]; olvl = getLevels(); } catch( Exception E ) { ApexPages.Message myMsg = new ApexPages.Message(ApexPages.Severity.FATAL, 'Controller failed with exception '+E); ApexPages.addMessage(myMsg); lo = null; } return lo; } public List<SelectOption> getLevels() { List<SelectOption> options = new List<SelectOption>(); options.add(new SelectOption('Option 1','Option 1')); options.add(new SelectOption('Option 2','Option 2')); options.add(new SelectOption('Option 3','Option 3')); return options; } public List<SelectOption> getolvl() { return olvl; } public PageReference save() { for(Account o: lo){ update o; System.debug('Updated Object='+o); } return null; } }

 

 enjoy!

 

 

This was selected as the best answer