2

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>
  • Before answering your question, I think there's a problem in your code. Do you want the user to be able to select multiple items? Because your selectedItems method can only return one item. Because you're filtering by Id. – Martin Lezer Mar 7 '17 at 9:58
  • @MartinLezer yes, I want to return multiple items. I tried to add selected ids to set, but it is still not working. So I decided to resolve this problem first. – Cassie Mar 7 '17 at 11:08
  • How are you re-rendering the cartForm as it is on a different page? Also where are you pre-populating the tvsList? – Saroj Bera Mar 7 '17 at 12:56
  • @SarojBera I edited some code here. I prepopulate tvsList in a constructor, just did not write it before because the whole controller and page code is too long. Also, I put all the forms on one page and hide or display them when it is needed. What I am trying to do here is to put all chosen items ids into set, but I`m not successful. – Cassie Mar 7 '17 at 13:23
3

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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