I have a JSF view that lists items in a collection in a Primefaces DataTable. The rightmost columns contain remove buttons. When a remove button is clicked, it is supposed to make an Ajax call, remove the corresponding item from the session variable Cart and update the view in-place. I would like the request and the view change to be as minimal as possible.
Here is what I have for this purpose:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Register user</title>
</h:head>
<h:body>
<f:view>
<h:form id="itemsForm">
<p:outputPanel id="items">
<p:dataTable value="#{cart.itemList}" var="item">
<p:column>
<f:facet name="header">
<h:outputText value="name" />
</f:facet>
<h:outputText value="#{item.product.description}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="quantity" />
</f:facet>
<h:outputText value="#{item.quantity}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="" />
</f:facet>
<p:commandButton icon="ui-icon-close" title="remove from cart">
<p:ajax listener="#{cart.removeItem}"
update="form:itemsForm"
process="#this" />
</p:commandButton>
</p:column>
<f:facet name="footer">
Total amount: ${cart.totalAmount}
</f:facet>
</p:dataTable>
</p:outputPanel>
</h:form>
</f:view>
</h:body>
</html>
Accordingly, I have the following method in Cart.java
public void removeItem() {
System.out.println("REMOVE REQUEST ARRIVED");
}
However, the removeItem method isn't even executing when I click a remove button.
So my questions are:
1) What is wrong with my Ajax call? What changes should I make to my XHTML?
2) How do I handle the request in the removeItem method and return a response?
3) How do I update the footer, which displays the totalAmount?
You can pass #{item} as a parameter of your method call in the actionListener.
Your .xhtml page should look like this:
<p:dataTable id="cartTable" value="#{cart.itemList}" var="item">
<p:column>
<f:facet name="header">
<h:outputText value="" />
</f:facet>
<p:commandButton icon="ui-icon-close" title="remove from cart"
actionListener="#{cart.removeItem(item)}" update="cartTable" />
</p:column>
</p:dataTable>
And this is the method removeItem of your ManagedBean:
#ManagedBean
#ViewScoped
public class Cart {
private List<Item> itemList;
public void removeItem(Item item) {
itemList.remove(item);
}
}
1) <p:commandButton uses ajax by default , so instead placing the p:ajax use the action or actionListener of the <p:commandButton
2) I would use the action of the button and return null
3) update="#form" should update the entire form and this will update the entire table
here an example of a working button (link) from my page , i used the f:setPropertyActionListener to "pass" some data to the delete method
<p:commandButton action="#{cart.removeItem}" icon="ui-icon-close" title="remove from cart" update="#form" process="#this" >
<f:setPropertyActionListener
target="#{cart.selectedItem}"
value="#{item}" />
</p:commandButton>
in your class add this
private Item selectedItem;
public Item getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(Item selectedItem) {
this.selectedItem = selectedItem;
}
Related
I have a scenario where I have to generate input text fields against each selection of a <pickList> in the same page. I am using PrimeFaces 5.2 and JSF 2.2.
Kindly advice.
Here goes answer:
XHTML:
<p:pickList id="PojoPickList"
value="#{editRoleAction.funcFieldDTO}" var="trnxDto"
effect="bounce" itemValue="#{trnxDto.fieldValue}"
itemLabel="#{trnxDto.fieldName}" showSourceControls="true"
showTargetControls="true" converter="pickListConverter">
<p:ajax event="transfer" update="#form"
listener="#{editRoleAction.transactionTransferToDestination}" />
<f:facet id="idar556" name="sourceCaption">#{msg.LBL_AVALIABLE_ROLES} </f:facet>
<f:facet id="idar557" name="targetCaption">#{msg.LBL_SELECTED_ROLES}</f:facet>
</p:pickList>
<h:panelGrid id="myGrid" width="400px;">
<p:dataTable value="#{editRoleAction.moduleTransactionList}" rendered="#{editRoleAction.moduleTransactionList.size() gt 0}" var="mainMenu">
<p:column>
<h:panelGrid columns="2">
<h:outputText value="Price of #{msg[mainMenu.labelId]}"/>
<p:inputText value="#{mainMenu.kioskType}"/>
</h:panelGrid>
</p:column>
</p:dataTable>
</h:panelGrid>
Java:
public void transactionTransferToDestination() {
List<FunctionalityFieldDTO> destTrnx = funcFieldDTO.getTarget();
for (FunctionalityFieldDTO dto : destTrnx) {
moduleTransactionList.add(dto);
}
}
I am using Primefaces 5.1 on glassfish 4. I have a view scoped bean behind an editable data table. As soon as the input text looses focus it returns to the old value and the cellEdit ajax event inside dataTable never fires.
For the last 2 weeks i have searched and tried numerous stackoverflow/ BalucC blog/ coderanch etc but I couldn't solve it. Input text simply does not retain the input. The edited text is actually present in the view because if i again try to edit the cell the edit value is there only until the input text has the focus.
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:form id="formbio">
<p:growl id="msgsbio" showDetail="true"/>
<p:contextMenu for="biolist" widgetVar="cMenu">
<p:menuitem value="Edit Cell" icon="ui-icon-search" onclick="PF('cellBio').showCellEditor();return false;"/>
<p:menuitem value="Hide Menu" icon="ui-icon-close" onclick="PF('cMenu').hide();"/>
</p:contextMenu>
<p:dataTable var="bres" value="#{aResultEntry.biolist}" id="biolist" editable="true" editMode="cell" widgetVar="cellBio" >
<f:facet name="header" >
<p:outputLabel value="Result input for Receipt # #{aResultEntry.voucher.receiptno}" />
</f:facet>
<p:ajax event="cellEdit" listener="#{aResultEntry.onCellEdit}" update=":allresulttabs:formbio:msgsbio"/>
<p:column headerText="Attribute" style="width:150px">
<h:outputText value="#{bres.testattribid.attributename}" />
</p:column>
<p:column headerText="Result" style="width:150px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{bres.resulttext}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{bres.resulttext}" style="width:100%" label="result"/>
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
<p:commandButton actionListener="#{aResultEntry.saveBioGrid()}" value="Save" id="Savebtn" update=":allresulttabs:formbio:msgsbio" immediate="true" />
</h:form>
My view scoped managed bean
#Named("aResultEntry")
#ViewScoped
public class AResultEntry implements Serializable {
,,,,,,,
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
Object evnt=event;
if(newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
......
}
I am using JSF Primefaces for my UI. I have a specific requirement about ajax on p:datatable. This is a sample page of my project:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:comp="http://java.sun.com/jsf/composite/components/">
<ui:define name="content">
<h:form id="form1">
<p:growl id="messages" showDetail="false" />
<p:panel header="Available Rows" style="width: 15%;">
<p:dataTable id="table" value="#{rowBean.rows}" var="row"
widgetVar="50" style="width: 60px;" editable="true">
<p:ajax event="rowEdit" listener="#{rowBean.onEdit}"
update="form1:messages" />
<p:ajax event="rowEditCancel" listener="#{rowBean.onCancel}"
update=":form1:messages" />
<p:column>
<f:facet name="header">
<h:outputText value="Row ID" />
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.id}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{row.id}"
style="width:100%" label="Row ID">
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Row Value" />
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{row.value}" />
</f:facet>
<f:facet name="input">
<p:inputText disabled="true" value="#{row.value}"
style="width:100%" label="Row Value">
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
<p:column style="width:6%">
<p:rowEditor />
</p:column>
</p:dataTable>
</p:panel>
<p:spacer height="5px;"/>
<p:panel id="createPanel" header="Create Row" closable="false" toggleable="true"
collapsed="true" style="width: 15%;">
<p:panelGrid columns="6">
<h:outputLabel for="rowBean" value="Row ID" />
<p:inputText value="#{rowBean.row.id}"
required="true" label="Row ID" style="width:125px" />
<h:outputLabel for="rowBean" value="Row Value" />
<p:inputText value="#{rowBean.row.value}"
required="true" label="Row Value" style="width:125px" />
<f:facet name="footer">
<p:commandButton value="Create" action="#{rowBean.createRow}"
update=":form1" />
</f:facet>
</p:panelGrid>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
Here I have a data table which lists down all the rows created. Each row is having id and value. Value is editable. There is one more panel within the form which creates new rows. Backing bean is pre-populated with all the created rows with #PostConstruct. Backing bean is having other methods to edit, cancel and create. This page is working and given below is the new requirement.
In some cases there can be an error associated with each row. If there is an error attached with a row, then the value text needs to be updated like a link. While clicking on the link, the row ID and a parameter needs to be passed to backing bean. With these params, backing bean fetches the error details and passes it to the page. Then the error message needs to be shown on a pop-up.
Can you tell me how to do this?
On the XHTML side:
<p:messages id="messages" showDetail="true" autoUpdate="true" closable="true" />
On the JAVA side, in the function you call when you press the button:
if(error) {
FacesContext.getCurrentInstance().addMessage(
null,
new FacesMessage(FacesMessage.SEVERITY_WARN, "Error",
"Your error message."));
}
PD: This is my first answer, i'm getting used to the post options, i'm sorry if you dont see my message properly ;)
Maybe like this?:
<f:facet name="output">
<h:outputText value="#{row.value}" rendered="#{!row.hasError}" />
<h:commandLink value="#{row.value}" rendered="#{row.hasError}" command="#{row.command(parameters..)}" />
</f:facet>
I have datatable with celledit, the ajax event does not fire on cell edit. The event listener does not get called.Thanks.
<ui:define name="content">
<h:form prependId="false" id="tForm">
<p:datatable id="dTable" value="#{bean.tData}" var="data"
editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{bean.updateData(data)}" />
<p:column>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{data.name}"></h:outputText>
</f:facet>
<f:facet name="input">
<p:inputText value="#{data.name}"></p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
</p:datatable>
</h:form>
</ui:define>
bean listener method
public void updateData(Data d){
logger.debug(d.getName());
}
I think you should use this instead:
<p:ajax event="cellEdit" listener="#{bean.updateData}" />
public void updateData(CellEditEvent event) {
Object newValue = event.getNewValue();
logger.debug(newValue.toString());
}
I am trying to user a form in 'panelGrid' to render values in a dataTable using <f:ajax>. However, when submitting using the <h:commandButton> the values sent are not displayed in the dataTable. I am not getting a stack or any console errors in the browsers.
This is the my xhtml (Simplified):
Product Catalog:
<p:tabView id="tabView" style="width: 65%" >
<p:tab id="books" title="Books">
<p:dataGrid var="book" value="#{saleBean.productList}" columns="3"
rows="9" paginator="true" paginatorTemplate="{CurrentPageReport}
{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink}
{LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="3,6,9">
<h:form id="product" >
<p:panel header="#{book.name}" style="text-align: center">
<h:panelGrid columns="1" style="width: 65%">
<!-- Add Book Images here -->
<h:outputText value="#{book.price}"/>
<h:outputLabel value="Dct (in dollars): " />
<h:inputText id="discount" value="#{saleBean.item.unit_discount}" style="width: 50%" />
<p:commandButton value="Add to Cart" update=":dataTableForm:sc"
action="#{saleBean.doAddItem}"/>
</h:panelGrid>
</p:panel>
</h:form>
</p:dataGrid>
</p:tab>
<p:tab id="arts" title="Art / Various">
<!-- Art Products to be added here -->
</p:tab>
<p:tab id="other" title="Other">
<!-- Various Products to be Added here -->
</p:tab>
</p:tabView>
<hr/>
<h1>Shopping Cart</h1>
<hr/>
<h:form id="dataTableForm">
<p:dataTable id="sc" value="#{saleBean.sd}" var="item" style="width: 60%">
<p:column>
<f:facet name="header">
<h:outputText value="Product"/>
</f:facet>
<h:outputText value="#{item.product_fk}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Quantity"/>
</f:facet>
<h:outputText value="#{item.quantity}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Unit Price"/>
</f:facet>
<h:outputText value="#{item.unit_Cost}"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Unit Discount"/>
</f:facet>
<h:outputText value="#{item.unit_discount}"/>
</p:column>
</p:dataTable>
</h:form>
</h:body>
This the bean (Simplified):
public String doAddItem()
{
item.setUnit_Cost(product.getPrice());
item.setProduct_fk(product);
item.setQuantity(1);
sd.add(item);
return "productCatalog";
}
According to PrimeFaces documentation :
http://www.primefaces.org/docs/vdl/3.4/primefaces-p/commandButton.html
Your actionListener="#{saleBean.doAddItem}" must use a function corresponding to that :
public void doAddItem(ActionListener event)
{
// do your stuff
}
To use action here is an example :
action="#{saleBean.doAddItem}"
public String doAddItem(void)
{
item.setUnit_Cost(product.getPrice());
item.setProduct_fk(product);
item.setQuantity(1);
sd.add(item);
return "productCatalog";
}
Try to use only pf components when you can eg p:datatable. Replace the button with a p:commandButton and use process and update instead of f:ajax.
Also maybe it will by better to include the p:datatable in the form too.