+ Start a Discussion
IvarIvar 

Problem with <apex:repeat> and checkboxes

Hi everybody.

 

I am hoping someone can give me a hint that pushes me in the right direction. What I am doing is creating a visualforce page that allows a client to register a lead and associate products the lead. On the page I am listing the products as checkboxes that are then processed by the controller. This was working properly when I displayed all products in a long list of checkboxes like this:

 

[ ] product 1

[ ] product 2

[ ] product ...n

 

Now I have a change request to break them down by families to display like this:

 

Category 1

  [ ] product 1

  [ ] product 2

Category 2

  [ ] product 3

  [ ] product 4

Category ...n

  [ ] product ...n

 

IInstead of delivering the products from the controller to the page as a List of Product2 I am now delivering it as a List of ProductCategory ( a custom class I wrote to encapsulate the name of each category and the products it contains).

 

My controller and page code for the relevant part are as follows:

 

 

public List<ProductCategory> getCategoryList(){
    	List<ProductCategory> finalList = new List<ProductCategory>();
    	//get all the products and put them into the list according to category
    	List<Product2> allProducts = getProductList();
    	
    	String lastCategoryName = '';
    	ProductCategory oneCategory = new ProductCategory();
    	oneCategory.strCategoryName = allProducts[0].Family;
    	
    	for( Product2 p: allProducts ){
    		if( p.Family != lastCategoryName ){
    			if( oneCategory.products.size() > 0 ) finalList.add(oneCategory);
    			//create new ProductCategory
    			oneCategory = new ProductCategory();
    			oneCategory.strCategoryName = p.Family;
    			oneCategory.products.add( new SelectOption(p.Id, p.Name));
    		}
    		else{
    			//add to existing
    			oneCategory.products.add( new SelectOption(p.Id, p.Name));
    		}
    		lastCategoryName = p.Family;
    	}
    	
    	return finalList;
    }
    
    public class ProductCategory{
    	public String strCategoryName {get;set;}
    	public List<SelectOption> products {get;set;}
    	
    	public ProductCategory(){
    		strCategoryName = 'noname';
    		products = new List<SelectOption>();
    		
    	}
    }

 

 

<apex:repeat value="{!categoryList}" var="category">
        <b>{!category.strCategoryName}</b>
         <apex:selectCheckboxes value="{!productsValues}" layout="pageDirection">
            <apex:selectOptions value="{!category.products}"/><br/>
         </apex:selectCheckboxes>
         <br/>
     </apex:repeat>

 

 

What I am trying to do is use an <apex:repeat> to cycle through each category, display it's name and then a series of checkboxes for each of the products it contains.

 

Now comes the problem.

 

This displays correctly but (perhaps understandably) each run of the <apex:repeat> overwrites the reference to productValues ( <apex:selectCheckboxes value="{!productsValues}" layout="pageDirection">) so that only the checked entries from the last iteration of repeat are delivered back to the controller.

 

Can anyone help me out here? Is there some way for me to accomplish this differently? How can I do this dynamically without having to hard-code a writeback variable for each category?

 

My thanks in advance,

Ivar

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

The way I'd approach this is to have the property that is backing the selectcheckboxes as a property on the ProductCategory class rather than at the controller level.  Then in your controller, when the user submits the page, you'd iterate the CategoryList and examine the chosen option for each category.

 

 

 

All Answers

bob_buzzardbob_buzzard

The way I'd approach this is to have the property that is backing the selectcheckboxes as a property on the ProductCategory class rather than at the controller level.  Then in your controller, when the user submits the page, you'd iterate the CategoryList and examine the chosen option for each category.

 

 

 

This was selected as the best answer
Bhawani SharmaBhawani Sharma
Correct, I am 100% agree with Bob. Instead of storing the selection on controller level property what you can do is : Create property "productsValues" in ProductCategory class and VF page access this as : on the controller level: Iterate the list and do whatever you want with the selection.
Bhawani SharmaBhawani Sharma
Correct, I am 100% agree with Bob. Instead of storing the selection on controller level property what you can do is : Create property "productsValues" in ProductCategory class and VF page access this as : Value="{!category.productsValues}" on the controller level: Iterate the list and do whatever you want with the selection.
IvarIvar

Thanks guys, both Bob and Bhawani. I will try this approach. I really appreciate your input!

IvarIvar

Trying to wrap my head around this :)

 

So, I should use a single List of the class ProductCategories  that handles both the output to the form and accepts the input from the form submit? 

 

 

Bhawani SharmaBhawani Sharma

Yup , You can use the sigle one for input and result

IvarIvar

Thanks a lot for your help guys, that did the trick of course :)

BN57BN57

Any chance you could post you final code please Ivar as I am having a very similar problem.

 

Thanks

 

Barry