How to realize rowToggle in primefaces 3.3? - datatable

I'm now using primefaces 3.3, but this version doesn't support event="rawToggle" for datatable. So I chose to use the onExpandStart instead of rowToggle, but I met with another problem. Here I want to put another datatable as the expanded row, so everytime I toggle one row in nodetable, I need to pass the nodeId of that row to backingbean to get all the contents of that node. If I have event="rowToggle", I can do it without any problem! But if I use the attribute onExpandStart of the dataTable, I cannot get the somenode.nodeId in the backingbean, anyone knows how to solve it?
I've also tried to put a hidden input tag <input type="hidden" name="hidden" value="#{somenode.nodeId}"/> inside the rowToggler, but the value I get in backingbean is null.
Have been worked on it for several days, but still no ideas. Help please please please!
<p:dataTable id="nodetable" value="#{nodeedit.list}" var="somenode"
styleClass="datatable" editable="true"
onExpandStart="#{nodeedit.toggle(somenode.nodeId)}" >
<p:ajax event="rowEdit" listener="#{nodeedit.save('node')}"/>
<p:column style="width:4%">
<p:rowToggler>
<h:form>
<input type="hidden" name="hidden" value="#{somenode.nodeId}"/>
</h:form>
</p:rowToggler>
</p:column>
<p:column>
<f:facet name="header">ID</f:facet>
<h:form>
<h:commandLink action="nodeedit">#{somenode.norder}</h:commandLink>
</h:form>
</p:column>
<p:column headerText="Name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{somenode.title}" />
</f:facet>
<f:facet name="input">
<p:inputTextarea value="#{somenode.title}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit" style="width:50px">
<p:rowEditor />
</p:column>
<p:rowExpansion>
<p:dataTable id="contentId" var="content"
value="#{nodeedit.contents}" id="contents" editable="true">
<p:ajax event="rowEdit" listener="#{nodeedit.save('content')}"/>
<p:column headerText="Text" style="width:450px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{content.text}" escape="false" />
</f:facet>
<f:facet name="input">
<p:inputTextarea value="#{content.text}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Edit" style="width:50px">
<p:rowEditor />
</p:column>
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
I have also tried another way. The Content of a Node is also an object, in the Node Class I have defined
List<LibContent> contents = new ArrayList<LibContent>();
so, like what siebzOr said, I wrote in my jsf something like:
<p:rowExpansion>
<p:dataTable var="content" value="#{somenode.content}">
**<p:ajax event="rowEdit" listener="#{nodeedit.save()}"/>**
<p:column>
<h:outputText value="#{content.someValue}" />
</p:column>
<!-- Other columns -->
</p:dataTable>
</p:rowExpansion>
and in backingbean nodeedit, I have
public void save() {
for (Content content : node.contents)
System.out.println("content.text");
}
I found that the content.text never changed no matter what I did in the page. But if I define List<Content> contents = new ArrayList<Content>() directly in nodeedit, it can get the new value!! That's why I tried to get the nodeId everytime I toggle the node-table and then update the contents in backingbean. Did I do something wrong with it?

p:rowExpansion is dynamic and loads it's data using AJAX. Something like this should work:
<h:form>
<p:dataTable value="#{nodeedit.list}" var="somenode" styleClass="datatable">
<p:column>
<p:rowToggler />
</p:column>
<!-- Your columns here -->
<p:rowExpansion>
<p:dataTable var="content" value="#{nodeedit.contentOf(somenode)}">
<p:column>
<h:outputText value="#{content.someValue}" />
</p:column>
<!-- Other columns -->
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
</h:form>
In your backing bean you should have a method to get the content of a node, in my example contentOf(Node node)
#Named // or #ManagedBean
#ViewScoped // or some other scope
public class Nodeedit
{
private List<Node> list;
//Getters and Setters
public List<SomeClass> contentOf(Node node)
{
// get and return the content of the node
}
}
If your Node has a method to get the Content you can do something like this in stead:
<p:rowExpansion>
<p:dataTable var="content" value="#{somenode.content}">
<p:column>
<h:outputText value="#{content.someValue}" />
</p:column>
<!-- Other columns -->
</p:dataTable>
</p:rowExpansion>
If a Node's content isn't a Collection of some sort I'm not sure it will work in a p:dataTable as the value.
I don't know what your classes look like so the above is just an idea.
Note also that I have put a h:form around the p:dataTable in stead of putting multiple forms in the p:dataTable itself. This is needed for multiple things like AJAX, selection, etc. You cannot nest forms.

Related

Attempting to edit a datatable nested inside of an editable datatable (Ajax Error I think)

I am attempting to make a nested (Through row expansion) data table editable which is inside of another editable datatable. It appears to be having a problem with the ajax rowEdit event. When I only have one datatable as editable e.g. comment out the nested ajax tag it works. But when I try to use both It returns an error saying :
Method not found: com.aglabexpress.Admin.Billing.CompleteInvoiceController#1146df77.editInvoiceItem(javax.faces.event.AjaxBehaviorEvent)"
Is this because of the double ajax events?
How do I rectify this while keeping both tables editable?
HTMLX:
<h:form id="mainForm" >
<p:dataTable id="mainFormTable" editable="true" value="#{completeInvoiceController.labNumberBill}" var="lab" paginator="true" rows="10" rowStyleClass="#{lab.colorStatus}">
<p:ajax event="rowEdit" listener="#{completeInvoiceController.editBill}" />
<p:column>
<p:rowToggler/>
</p:column>
...
...
<p:column headerText="Date" footerText="Date">
<p:cellEditor>
<f:facet name="output">
<p:outputLabel value="#{lab.creationDateString}" />
</f:facet>
<f:facet name="input">
<p:calendar value="#{lab.creationDate}" />
</f:facet>
</p:cellEditor>
</p:column>
...
...
<p:column headerText="Edit">
<p:rowEditor />
</p:column>
<p:rowExpansion>
<p:dataTable value="#{lab.invoiceItems}" var="item" editable="true">
<p:ajax event="rowEdit" listener="#{completeInvoiceController.editInvoiceItem}" />
...
...
<p:column headerText="Description" footerText="Description">
<p:cellEditor>
<f:facet name="output">
<p:outputLabel value="#{item.description}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{item.description}" />
</f:facet>
</p:cellEditor>
</p:column>
...
...
<p:column headerText="Edit">
<p:rowEditor />
</p:column>
</p:dataTable>
</p:rowExpansion>
Beans
public void editInvoiceItem(RowEditEvent event){
InvoiceItemConstructor itc = (InvoiceItemConstructor) event.getObject();
if(cih == null){
cih = new CompleteInvoiceHelper();
}
cih.updateItem(itc);
}
public void editBill(RowEditEvent event){
CompleteInvoiceLabNumberBill bill = (CompleteInvoiceLabNumberBill) event.getObject();
if(cih == null){
cih = new CompleteInvoiceHelper();
}
cih.updateBill(bill);
}
You need to replace your nested datatable event method signature to
public void editInvoiceItem(javax.faces.event.AjaxBehaviorEvent event)
Is this because of the double ajax events?
Yes. This is a known issue (which had been originally reported for nested p:tabView) which seems to be fixed since PrimeFaces 5.0.
You can find further information in a thread (from July 2013) of the PrimeFaces forum

how to detect which row is concerned when changing autocomplete object inside datatable primefaces

I have this datatable :
<p:commandLink value="ajouter Ligne" update="lesarticles"
process="#this" actionListener="#{commandeMB.addLigne}" />
<p:dataTable id="lesarticles" var="car" widgetVar="carsTable"
rowKey="#{car.ligneCommandeFournisseurId}" selectionMode="single"
selection="#{commandeMB.selectedLigneCommandeFournisseur}"
value="#{commandeMB.commande.ligneCommandeFournisseurs}"
>
<p:column headerText="Numero">
<p:autoComplete id="art" required="true" var="p"
itemLabel="#{p.numero}" itemValue="#{p}" dropdown="true"
requiredMessage="Valeur requise" value="#{car.article}"
forceSelection="true" converter="#{articleConverter}"
completeMethod="#{commandeMB.completeArticle}">
<p:column>#{p.numero}</p:column>
<p:column>#{p.designation}</p:column>
<p:ajax event="itemSelect" listener="#{commandeMB.handleSelect}"
update="designation unite pu" />
</p:autoComplete>
<p:message for="art" display="text" />
</p:column>
<p:column headerText="designation">
<h:outputText id="designation"
value="#{car.article.designation}" />
</p:column>
<p:column headerText="unité">
<h:outputText id="unite"
value="#{car.article.unite.libelle}" />
</p:column>
<p:column headerText="PU">
<h:inputText id="pu" styleClass="monpu"
value="#{car.PUAchat}" />
</p:column>
<p:column headerText="Quantité">
<h:inputText binding="#{qte}" styleClass="maqte" value="#{car.qte}" >
</h:inputText>
</p:column>
<p:column headerText="Mt">
<h:outputText id="mt" styleClass="monmt"
value="#{car.mtLigne}" />
</p:column>
</p:dataTable>
I want when the user select one article(product in english) (througt autocomplete) I can detect which row is concerned by this selection to do do some treatements on managed bean side
as you see in the code I retrieve the selected article by :
public void handleSelect(SelectEvent event){
Article art = (Article) event.getObject();
}
but I want to retrieve also the row which contains this new article in the datatable
how can I achieve this
thank you in advance
<p:dataTable rowIndex="myIndex"/>
Then you can bind this value via;
<f:setPropertyActionListener target="#{bean.index}" value="#{myIndex}"/>
Or;
<f:param name="myIndex" value="#{myIndex}"></f:param>
To be able to retrieve the value which comes with f:param:
Map<String, String> map = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
int index = Integer.parseInt(map.get("myIndex"));
You can put those in a p:commandLink, p:commandButton or p:ajax.
I resolved this problem by that :
<p:column headerText="Numero">
<p:autoComplete id="art"
required="#{commandeMB.validation}" var="p"
itemLabel="#{p.numero}" itemValue="#{p}" dropdown="true"
requiredMessage="Valeur requise" value="#{car.article}"
forceSelection="true" converter="#{articleConverter}"
completeMethod="#{commandeMB.completeArticle}">
<p:column>#{p.numero}</p:column>
<p:column>#{p.designation}</p:column>
<p:ajax event="itemSelect" listener="#{commandeMB.handleSelect}"
update="designation unite pu mt" />
</p:autoComplete>
<p:message for="art" display="text" />
</p:column>
and in the managed bean I retrieve the concerned row by this :
FacesContext context = FacesContext.getCurrentInstance();
LigneCommandeFournisseur ligne_concernee =
context.getApplication().evaluateExpressionGet(context, "#{car}", LigneCommandeFournisseur.class);

Incell Editing in datatable for primefaces not sending edited values to event

I want a table with in-line editing option in datatable. I am able to write full code but when i am clicking on edit button, the value which i am getting from event object from server side is same as old. I am not getting new values.
how to get new values from event object.
<p:dataTable id="dataTable"
var="osList"
value="#{WLMPortalViewController.allOSInfo}" rowKey="#{osList.osName}"
paginator="true" rows="5"
paginatorPosition="bottom"
editable="true" >
<p:ajax event="rowEdit" update="#this" listener="#{WLMPortalDataController.saveOSData}"/>
<p:column headerText="Options" >
<p:rowEditor />
</p:column>
<p:column headerText="Version" >
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{osList.osVersion}" />
</f:facet>
<f:facet name="input">
<p:inputText id="inputosVer" required="true" requiredMessage="* Version can't Empty." value="#{osList.osVersion}" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
and my server side code look like this
public void saveOSData(RowEditEvent event){
System.out.print(event.getObject());
}

Unable to populate values obtained from ajax call using PrimeFaces

Hi
I have made an ajax call using primefaces [p:ajax]. The call to the listener was successful and it returned the required values. To update these properties in xhtml, I have checked the DOM source, to find out the exact ID of the column, using which the column or property would be updated. But, in this case the fields are not getting the values.
The code I used in this case is
<p:dataTable id="table1" var="recepit" rowIndexVar="rowIndex" value="#{ReceiptDetailsBean.iterativeList}" scrollable="true" height="120px" styleClass="leftTable">
<p:column style="background-color: #EFF2F9">
<f:facet name="header">
<h:outputText value="SL NO" />
</f:facet>
<h:outputText value="#{rowIndex+1}" />
</p:column>
<p:column >
<f:facet name="header">
<h:outputText value="Buss." />
</f:facet>
<h:selectOneMenu id="selectOneCb" value="#{ReceiptDetailsBean.bussCode}" >
<f:selectItem itemLabel="V_BUSS_CODE" itemValue=""/>
<f:selectItems value="#{ReceiptDetailsBean.rdetails}" var="model" itemLabel="#{model.buss}" itemValue="#{model.buss}"/>
<p:ajax update="mainForm:table1:#{rowIndex}:receiptCode, mainForm:table1:#{rowIndex}:referenceType" actionListener="#{ReceiptDetailsBean.obtainReceiptDatabasedOnBussCode}" event="change"/>
</h:selectOneMenu>
</p:column>
<p:column id="receiptCodeCol">
<f:facet name="header">
<h:outputText value="Receipt Code" />
</f:facet>
<h:inputText value="#{ReceiptDetailsBean.receiptCode}" id="receiptCode" style="font-family: verdana;font-size: 10px;width:80px;height:15px" />
</p:column>
<p:column id="receiptTypeCol">
<f:facet name="header">
<h:outputText value="Ref Type" />
</f:facet>
<h:inputText value="#{ReceiptDetailsBean.receiptType}" id="referenceType" style="font-family: verdana;font-size: 10px;width:80px;height:15px"/>
</p:column>
</p:dataTable>
</div>
</p:tab>
<p:tab title="Print">
</p:tab>
</p:tabView>
</h:form>
The id from the DOM view source was table1:0:receiptCodeHotKey:receiptCode
What would be the problem for the data to not get populated in the field.
I think the source of the problem is your usage of h:form. You don't need to put it around each single input element. Put one h:form around the datatable and then check again the generated ids.
Then it should be something like (example for first row with rowindex 0):
formId:table1:0:receiptCode

Ajax call is made but the related fields are updated only after page refresh

I have tried making an ajax call for a selectOneMenu using JSF 2 and primefaces 2.2. The actionListener method is being called. But the columns I specified in the update attribute are not getting updated. When I refersh the page, I could find the updated values. Please help me out in this.
The code I used was
<h:form id="mainForm" prependId="false">
<p>
<p:tabView>
<p:tab title="Receipt">
<p:dataTable id="table1" var="recepit" rowIndexVar="rowIndex" value="#{ReceiptDetailsBean.iterativeList}" scrollable="true" height="120px" styleClass="leftTable">
<p:column style="background-color: #EFF2F9">
<f:facet name="header">
<h:outputText value="SL NO" />
</f:facet>
<h:outputText value="#{rowIndex+1}" />
</p:column>
<p:column >
<f:facet name="header">
<h:outputText value="Buss." />
</f:facet>
<h:selectOneMenu id="selectOneCb4" value="#{ReceiptDetailsBean.bussCode}" >
<f:selectItem itemLabel="V_BUSS_CODE" itemValue=""/>
<f:selectItems value="#{ReceiptDetailsBean.rdetails}" var="model" itemLabel="#{model.buss}" itemValue="#{model.buss}"/>
<p:ajax update="table1:#{rowIndex}:receiptCode, table1:#{rowIndex}:referenceType" actionListener="#{ReceiptDetailsBean.obtainReceiptDatabasedOnBussCode}" event="change"/>
</h:selectOneMenu>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Receipt Code" />
</f:facet>
<h:inputText value="#{ReceiptDetailsBean.receiptCode}" id="receiptCode" style="font-family: verdana;font-size: 10px;width:80px;height:15px" onkeypress="return showForhotKey(event,'#{rowIndex}');"/>
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="Ref Type" />
</f:facet>
<h:inputText value="#{ReceiptDetailsBean.receiptType}" id="referenceType" style="font-family: verdana;font-size: 10px;width:80px;height:15px" onkeypress="return showForhotKey(event,'#{rowIndex}');"/>
</p:column>
</p:dataTable>
</p:tab>
<p:tab title="Print">
</p:tab>
Try f:ajax instead of p:ajax and re-render the whole form to get closer to the problem source :
<h:selectOneMenu id="selectOneCb4" value="#{ReceiptDetailsBean.bussCode}" >
<f:selectItem itemLabel="V_BUSS_CODE" itemValue=""/>
<f:selectItems value="#{ReceiptDetailsBean.rdetails}" var="model"
itemLabel="#{model.buss}" itemValue="#{model.buss}"/>
<f:ajax render="#form"
listener="#{ReceiptDetailsBean.obtainReceiptDatabasedOnBussCode}"/>
</h:selectOneMenu>
This should work as stated in my answer to your previous question.
Partial updates of dataTables and ajax updates of dataTables triggered from a component within the dataTable are not working in the 2.2 version of Primefaces. This is a known bug that may have been resolved in version 3.
One suggestion you can try is to use a single form for each dataTable and only update elements from within that one form.

Resources