[SalesForce] How to pass multiple parameters using custom button

I have 4 main blocks pages on one page with lists of products in different categories and Shopping cart page.

I want by click on the custom button Add to cart (near each item on the product page) put selected items into the list or any other collection, which should be displayed on the Shopping cart page.

I have this problem – everytime I click on the button my list of items stays empty. I tried different ways, but all I could get is only one item displayed. Somehow, selected items are not passed to the page, though I select them by chosen ID.

Here is the code for Shopping cart page:

  <apex:form id="cartForm" >
        <apex:outputPanel id="productsDetail">
            <apex:pageBlock title="Your Shopping Cart" id="cartBlock">
                <apex:pageBlockTable value="{!shoppingCart}" var="item">
                    <apex:column >
                        <apex:commandLink value="{!item.Name}" >
                            <apex:param name="id" value="{!chosenItemId}"/>
                        </apex:commandLink>
                        <apex:pageBlockSection >
                            <apex:outputText value="{!item.Price__c}" id="itemPrice"/><br/>
                        </apex:pageBlockSection>-->
                        <apex:commandButton value="Buy" action="{!buyProduct}" id="buyButton"></apex:commandButton>
                    </apex:column>
                </apex:pageBlockTable>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>

Common controller for all 4 pages with only relevant for this task methods and variables:

 public with sharing class ProductPagesController {
public List<Product__c> shoppingCart { set; get; }
public Set<String> selectedIds { set; get; }
private String currentPage =   ApexPages.currentPage().getParameters().get('Id');
public Id chosenItemId { set; get; }
public List<Product__c> tvsList { set; get; }

public ProductPagesController() {
    renderTV = false;
    renderShoppingCart = false;
    tvsList = selectTVsList();
    selectedIds = new Set<String>();
    shoppingCart = new List<Product__c>();
}

private Product__c selectedItems(Id itemId) {
    Product__c items = [
            SELECT Id
                    , Name
                    , Price__c
                    , Description__c
                    , Image__c
                    , Quantity__c
            FROM Product__c
            WHERE Id=:itemId
    ];
    return items;
}

 public PageReference addProductToShoppingCart() {
     Product__c shoppingCartItem;
        for(Id itemId : selectedIds){
            shoppingCartItem = selectedItems(itemId);
            shoppingCart.add(shoppingCartItem);
        }

        update shoppingCart;
        return null;
    }
}

One of the products page (TV category):

<apex:form id="tvsForm">
        <apex:outputPanel id="tvsDetail">
            <apex:pageBlock title="TVs" id="tvsBlock">
                <apex:pageBlockTable value="{!tvsList}" var="tv">
                    <apex:column >
                        <apex:commandLink value="{!tv.Name}" >
                            <apex:param name="id" value="{!tv.Id}"/>
                        </apex:commandLink>
                        <apex:pageBlockSection >
                            <apex:image value="{!URLFOR($Resource.TV, tvsImages[tv.Name])}" id="tvImage"/>
                        </apex:pageBlockSection>
                        <apex:pageBlockSection >
                            <apex:outputText value="{!tv.Price__c}" id="tvPrice"/><br/>
                            <apex:outputText value="{!tv.Description__c}"/>
                        </apex:pageBlockSection>
                        <br/>
                        <apex:commandButton value="Add to cart" action="{!addProductToShoppingCart}" id="monitorButton" reRender="cartForm">
                            <apex:param name="itemsId" value="{!tv.Id}" assignTo="{!selectedIds}"></apex:param>

                        </apex:commandButton>
                        <br/><br/>
                    </apex:column>
                </apex:pageBlockTable>

                <apex:pageBlockSection >
                    <apex:outputText value="There are {!tvsQuantity} products in this category" id="productsNumber"/><br/>
                </apex:pageBlockSection>
            </apex:pageBlock>
        </apex:outputPanel>
    </apex:form>

Best Answer

It looks like you never add any Id's to your list of selected Ids. Instead of passing the entire list, (and then running dml operations in a loop, consuming more queries than needed), pass one id along at a time, and keep the rest of the ids listed in memory. I've written up an example of code which might help you get more than just the one record into your list.

You need to provide a single item id at a time, and pass that id from the commandButton, to the variable chosenItemId. This acts as a placeholder for the id the user currently added to the cart.

You then take this id, and call getProduct, using that id as a parameter, to get the Product__c record (This step could be optimized out, by keeping the product data in the controller).

Use add to add that variable to your list of selected products, return null to refresh the page, and you should have a list of records which continues populating as the user clicks more records.

I'm not sure why you were calling update shoppingCart; without modifying any of the fields on the product list and adding a seemingly pointless dml update to a query, so I've removed it in my example code. I've also renamed some functions, and left out the constructor and other unnecessary code, but you should be able to merge this into your code without issue.

Class

public with sharing class ProductPagesController {

    /** ...  */

    public Id chosenItemId { set; get; }
    public Set<Id> selectedIds { set; get; }
    public List<Product__c> shoppingCart { set; get; }


    /** ...  */

    private Product__c getProduct(Id itemId) {
        Product__c item = [
                SELECT Id
                        , Name
                        , Price__c
                        , Description__c
                        , Image__c
                        , Quantity__c
                FROM Product__c
                WHERE Id=:itemId
        ];
        return item;
    }

    public PageReference addProductToShoppingCart() {
        shoppingCart.add(getProduct(chosenItemId));
        chosenItemId = null; 

        return null; 
    }
}

Page

<apex:commandButton value="Add to cart" action="{!addProductToShoppingCart}" id="monitorButton" reRender="cartForm">
    <apex:param name="itemId" value="{!tv.Id}" assignTo="{!chosenItemId}"></apex:param>
</apex:commandButton>

As a side note, if you're new to apex and visualforce development, I always recommend the Salesforce Trailheads as a way to learn the platform in a safe environment.

Related Topic