Toggle the value of apex:commandbutton

I am using a pageblocktable that has a column of buttons next to each product that says “add to cart”, I need to toggle this button to “remove” once the product has been added to the cart.

Using the help from this link:
Toggle Command Button Value from Ascending to Descending

I was able to toggle a button from “Add to cart” to “Remove” however it is toggling ALL the buttons in the column and I need it to toggle each button individually as it is clicked.

Here is my code:

<apex:pageBlockTable value="{!products}" var="item" id="products">
                    <apex:column headerValue="Product" width="60%">
                        <apex:outputText value="{!item.Name}" />
                    </apex:column>
                    <apex:column headerValue="Product Code" width="25%">
                        <apex:outputText value="{!item.ProductCode}" />
                    </apex:column>
                    <apex:column headerValue="Product Category" width="15%">
                        <apex:outputText value="{!item.Family}" />
                    </apex:column>
                     <apex:column width="5%" style="text-align: center;">
                            <apex:commandButton value="Add to cart" action="{!AddToCart}" reRender="products" immediate="true" id="AddToCartBtn" rendered="{!showAdd}">
                                    <apex:param value="{!item.Id}" assignTo="{!productItemId}" name="addToCart"/>
                                </apex:commandButton>
                                <apex:commandButton value="Remove" action="{!RemoveFromCart}" reRender="products" immediate="true" id="RemoveFromCartBtn" rendered="{!showRemove}">
                                    <apex:param value="{!item.Id}" assignTo="{!productItemId}" name="removeFromCart"/>
                                </apex:commandButton>
                    </apex:column>
                </apex:pageBlockTable>

Any help would be phenomenal – Thanks!

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You need to customize showAdd and showRemove to use specific values. There’s several ways you could do this, but the least painful way to do so right now without writing a ton of code is to make showAdd and showRemove per-item. Here’s how that would look:

// In your controller
public Map<Id, Boolean> shouldShowAddButton { get; set; }

And in your page:

... First button
rendered="{!shouldShowAddButton[item.id]}">

... Second button
rendered="{!not shouldShowAddButton[item.id]}">

In your constructor, make sure you create a new Map<Id, Boolean> for shouldShowAddButton, and update your addToCart and removeFromCart functions to update this map accordingly.

A word of caution: Make sure your map contains a value for every product that may be rendered, or your page will crash. Visualforce doesn’t like to reference non-existent keys.

In the future, you should probably consider a Wrapper class. It takes a bit more work, but has the advantage of being easier to manage. Here’s one possible implementation:


public class Extension {
    Set<Id> cartIds = new Set<Id>();

    public class Wrapper {
        public Product2 product { get; set; }
        Extension extension;
        Wrapper(Extension e, Product2 p) {
            extension = e;
            product = p;
        }
        public void addToCart() {
            extension.cartIds.add(product.Id);
        }
        public void removeFromCart() {
            extension.cartIds.remove(product.Id);
        }
        public Boolean getShowAdd() {
            return !getShowRemove();
        }
        public Boolean getShowRemove() {
            return extension.cartIds.contains(product.Id);
        }
    }
    public Wrapper[] getProducts() {
        Wrapper[] results = new Wrapper[0];
        for(Product2 record:[...]) {
            results.add(new Wrapper(this, record));
        }
        return results;
    }
}

At this point, your products are “wrapped” inside some logic that let you control individual values, so you have to change your entire page slightly:

<apex:pageBlockTable value="{!products}" var="item" id="products">
    <apex:column headerValue="Product" width="60%">
        <apex:outputText value="{!item.product.Name}" />
    </apex:column>
    <apex:column headerValue="Product Code" width="25%">
        <apex:outputText value="{!item.product.ProductCode}" />
    </apex:column>
    <apex:column headerValue="Product Category" width="15%">
        <apex:outputText value="{!item.product.Family}" />
    </apex:column>
    <apex:column width="5%" style="text-align: center;">
        <apex:commandButton value="Add to cart" action="{!item.addToCart}" reRender="products" id="AddToCartBtn" rendered="{!item.showAdd}" />
        <apex:commandButton value="Remove" action="{!item.removeFromCart}" reRender="products" immediate="true" id="RemoveFromCartBtn" rendered="{!item.showRemove}" />
    </apex:column>
</apex:pageBlockTable>

This removes the complexity of having to pass parameters, etc, by letting the wrapper do the heavy lifting for you. Communication between the individual wrapper item and the extension is handled by way of a memory reference (new Wrapper(this, record).


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x