How to disable rest of the rows in a dynamic <h:dataTable> when one of the rows is selected?

There is a list that is dynamically generated at runtime. I am using a dataTable to represent it. Inside each row is a dropdown list. As soon as the user selects a value from the drop down list in a row, then all the other rows must be disabled.?

<h:dataTable value="#{user.orderList}" var="item">

    <h:column>              
        <h:selectOneMenu value="#{user.sometuff}" >
                <f:selectItems value="#{user.someItems}" />
        </h:selectOneMenu>
    </h:column>

</h:dataTable>

How can I achieve this with <f:ajax>?

Upvotes: 0

Views: 121

Answers (1)

tt_emrah
tt_emrah

Reputation: 1053

here is a working example.

imho, it's way easier to implement with ajax4jsf (richfaces), using a4j:repeat and a4j:ajax tags.

xhtml code:

<h:form id="form">

    <h:dataTable id="tableId" value="#{user.orderList}" var="item">

        <h:column>              
            <h:selectOneMenu value="#{item.selectedItem}" disabled="#{user.oneItemSelected and (item.selectedItem == null || item.selectedItem == '')}">
                 <f:selectItems value="#{user.selectItemList}" />
                 <f:ajax execute="@this" render="@form" listener="#{user.updateSelectionFlag}"></f:ajax>
            </h:selectOneMenu>
        </h:column>

    </h:dataTable>

</h:form>

order item code:

public class Order implements Serializable
{
    private static final long serialVersionUID = 1L;

    private String selectedItem;

    public String getSelectedItem() {
        return selectedItem;
    }

    public void setSelectedItem(String selectedItem) {
        this.selectedItem = selectedItem;
    }
}

managed bean code:

@Named
@ViewScoped
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private List<Order> orderList;
    private List<SelectItem> selectItemList;
    private boolean oneItemSelected;

    public List<SelectItem> getSelectItemList() {
        if (selectItemList == null)
        {
            selectItemList = new ArrayList<SelectItem>();
            selectItemList.add(new SelectItem("", "---Please Choose---"));
            selectItemList.add(new SelectItem("1", "Item 1"));
            selectItemList.add(new SelectItem("2", "Item 2"));
            selectItemList.add(new SelectItem("3", "Item 3"));
            selectItemList.add(new SelectItem("4", "Item 4"));
        }
        return selectItemList;
    }

    public List<Order> getOrderList() {
        if (orderList == null)
        {
            orderList = new ArrayList<Order>();
            for (int i=0 ; i<4 ; i++)
            {
                orderList.add(new Order());
            }
        }
        return orderList;
    }

    public boolean isOneItemSelected() {
        return oneItemSelected;
    }

    public void updateSelectionFlag()
    {
        oneItemSelected = false;
        for (int i=0 ; i<getOrderList().size() ; i++)
        {
            Order order = getOrderList().get(i);
            if (order.getSelectedItem() != null && !order.getSelectedItem().equals(""))
            {
                oneItemSelected = true;
                break;
            }
        }
    }
}

by the way, instead of checking the whole array in updateSelectionFlag, it's better to check only the submitted item's value. but i couldn't figure out how to get the clicked row index of h:dataTable. doing a binding prevents combo values from being submitted, and datatable does not provide a varStatus attribute like ui:repeat does.

Upvotes: 1

Related Questions