Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skip processing of input components inside p:dataTable when a button is pressed which only needs to get selected rows

I have prepared just a simple example of shopping basket for the demonstration purpose only.

The XHTML page:

<p:dataTable id="cartDataTable" value="#{testManagedBean.qtyList}"
             var="cart"
             selection="#{testManagedBean.selectedQtyList}"
             rowKey="#{cart.id}">

    <p:column selectionMode="multiple" />

    <p:column>
        <h:outputText value="#{cart.id}"/>
    </p:column>

    <p:column>
        <p:inputText value="#{cart.qty}"/>
    </p:column>
</p:dataTable>

<p:commandButton value="Delete" process="@this cartDataTable"
                 actionListener="#{testManagedBean.delete}"/>

The managed bean:

@ManagedBean
@SessionScoped
public final class TestManagedBean implements Serializable
{
    private List<Cart>qtyList; //Getter only.
    private List<Cart>selectedQtyList; //Getter and setter.
    private static final long serialVersionUID = 1L;

    @PostConstruct
    public void init()
    {
        qtyList=new ArrayList<>();
        qtyList.add(new Cart(1, 1));
        qtyList.add(new Cart(2, 1));
        qtyList.add(new Cart(3, 2));
        qtyList.add(new Cart(4, 1));
        qtyList.add(new Cart(5, 3));
    }

    public void delete()
    {
        for(Cart cart:selectedQtyList) {
            System.out.println(cart.getId()+" : "+cart.getQty());
        }

        System.out.println("Perform deletion somehow.");
    }
}

This is a session scoped JSF managed bean holding a shopping cart. The class Cart is quite intuitive with only two properties of type Integer namely id and qty and a parameterized constructor.

When the given delete button is clicked, we need to set the selected rows to be deleted to the backing bean.

To set the selected rows, the process attribute of <p:commandButton> is set to @this and cartDataTable which sets the selected rows to the bean's property selectedQtyList, when this button is pressed.

Since this a session scoped bean, if a user unknowing modifies the quantity in the cart in any row/s prior to pressing the delete button then, new value/s of quantity is/are set to list qtyList.

This should happen only when updating the cart but certainly must not happen anymore while deleting row/s.

In real application, deletion is done in a separate view scoped bean.

If the process attribute of <p:commandButton> is set to @this only (i.e process="@this" removing cartDataTable from this attribute) then, selected rows are not set to the managed bean property selectedQtyList.

How to proceed with this?

like image 393
Tiny Avatar asked Jul 13 '14 18:07

Tiny


1 Answers

As far as I understand, you basically want to prevent <p:inputText value="#{cart.qty}"> from being processed (updating the model value) when the delete button is pressed. Theoretically, it should work to only specify the selection column in the process attribute, but unfortunately <p:dataTable> didn't eat that. Also, immediate="true" on the button won't help as the <p:column selectionMode> doesn't support that.

Your best bet is making sure that rendered attribute of the input field only evaluates true if the delete button is not pressed or when JSF is rendering the response.

<p:inputText ... rendered="#{empty param[delete.clientId] or facesContext.renderResponse}" />
...
<p:commandButton binding="#{delete}" ... />

JSF namely won't process input components which aren't rendered. The bean scope is irrelevant in this case.

like image 51
BalusC Avatar answered Sep 21 '22 21:09

BalusC