I have a datatable with custom sorting. It sorts the array containing my data and then the table is refreshed via ajax call. The table has multiple columns with simple text in it, and an additional column with command button and command links. My problem is, that this buttons and links are not refreshed. It means that if I click the button on the second row, it affects the element which was in the second row before sorting.
This is the page code:
<h:body>
<h:form class="page_frame">
<a4j:jsFunction name="sortTable" render="data_table#body"
actionListener="#{MyBean.getFilteredData()}" >
<a4j:param name="param1" assignTo="#{MyBean.newSortBenchmark}"/>
</a4j:jsFunction>
<rich:dataTable value="#{MyBean.getFilteredData()}" var="data" id="data_table"
rowClasses="odd-row, even-row" styleClass="even_odd"
style="width: 900px;">
<rich:column >
<f:facet name="header">
<span onclick="sortTable('name')">Name</span><br/>
</f:facet>
<h:outputText value="#{data.name}"/>
</rich:column>
//more similar columns with sorting
<rich:column>
<f:facet name="header">Start/Stop</f:facet>
<a4j:commandButton value="Start" action="#{MyBean.startProcess(data)}"
rendered="#{!data.processRunning}"
render="data_table#body"
execute="#this" style="width: 100%" >
</a4j:commandButton>
<a4j:commandButton value="Stop" action="#{MyBean.stopProcess(data)}"
rendered="#{data.processRunning}"
render="data_table#body"
execute="#this" style="width: 100%" >
</a4j:commandButton>
</rich:column>
<rich:column>
<f:facet name="header">Actions</f:facet>
<a4j:region>
<a4j:commandLink action="#{MyBean.showDetails(data)}" oncomplete="#{rich:component('detailsPanel')}.show()" render="details_table" >
<h:graphicImage id="details_image" name="details.png" library="images" style="border:0" />
<rich:tooltip followMouse="true" target="details_image" value="Details" />
</a4j:commandLink>
</a4j:region>
//more similar command links, also not working
</rich:column>
</rich:dataTable>
</h:form>
</h:body>
And the filtering is done by:
Collections.sort(dataList, new dataComparator(sortBenchmark));
Related
I have a screen in my Richfaces application which uses a datatable and datascroller, with validation to ensure that data is filled.
( example to simulate the problem, full example can be found here
<h:form id="articleForm" >
<h:panelGroup layout="block">
<rich:messages globalOnly="true" />
<rich:dataTable value="#{productModifyBean.articles}" var="article" id="articleTable"
rows="15" >
<rich:column headerClass="headerOverflow artNrColumn">
<f:facet name="header">
<h:outputText value="articleNumber" />
</f:facet>
<h:outputText value="#{article.articleNumber}"/>
</rich:column>
<rich:column headerClass="headerOverflow shortNameColumn">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{article.shortName}" />
</rich:column>
<rich:column headerClass="headerOverflow quantityColumn" >
<f:facet name="header">
<h:outputText value="Quantity" />
</f:facet>
<h:inputText value="#{article.quantity}" required="true"
requiredMessage="This is required" converterMessage="Error conversion"
id="modifyArticleFormatQuantity" >
</h:inputText>
<rich:message for="modifyArticleFormatQuantity" errorClass="errorColorRed" />
</rich:column>
</rich:dataTable>
<rich:dataScroller for="articleTable" renderIfSinglePage="false" boundaryControls="show" fastControls="hide" execute="#form" render="articleTable"
stepControls="show" style="float:right;" />
</h:panelGroup>
<br style="clear: both" />
<br style="clear: both" />
<div align="right" style="clear: both">
<a4j:commandButton value="#{msgs['button.modify'] }" styleClass="submitButton"
render="#{facesContext.validationFailed ? '#none' : 'articleForm'}"
actionListener="#{productModifyBean.modifyProduct}">
</a4j:commandButton>
</div>
</h:form>
Data validation should happen when the user presses the submit button ( to save the data) , and when the user using the pagination to go to a different page.
When clicking the submit button after leaving one field empty, the behaviour is normal : it shows an empty field with the remark 'this is required'
However, when instead moving to a different page ( for example clicking on the '2' page button ) , validation happens correctly, but the old value is put back into the screen, thus stating that the value should be filled but showing it filled in with a value.
Anyone have any idea what the reason for this problem could be, and how to resolve it ? Is this a bug in RichFaces, or am I overlooking something ?
I found the solution by trial and error :
If I change the datascroller to use render="#region" , the screen is correctly rendered.
<rich:dataScroller for="articleTable" renderIfSinglePage="false" boundaryControls="show" fastControls="hide" execute="#form" render="articleTable"
stepControls="show" style="float:right;" />
In an application based on Seam 2.2.1, JSF 1.2, Richfaces 3.3.3, I have a datatable with clickable rows.
In the last column, I have an icon (trash). Clicking here should execute a different method (delete). The standard onRowClick event should not apply.
Is there any easy way to accomplish this?
<rich:panel headerClass="panelHeader" styleClass="panel">
<f:facet name="header">Header</f:facet>
<rich:dataTable id="myTable" value="#{myModel}" var="k">
<a4j:support event="onRowClick" action="#{myAction.selectItem(k, facesContext.viewRoot.viewId)}"
reRender="myTable"/>
<rich:column>
<f:facet name="header">
<h:outputText value="Normal Column - should be clickable"/>
</f:facet>
<h:outputText value="#{k.name}"/>
</rich:column>
<rich:column >
<f:facet name="header">
<h:outputText value="Only Click on Icon should react to Mouseclick"/>
</f:facet>
<s:graphicImage value="/img/bin_closed.gif">
<a4j:support event="onclick"
action="#{myAction.deleteItem(k)}"
reRender="myTable"
ajaxSingle="true" limitToList="true"
onsubmit="if(!confirm('Really?')) { return false; }" />/>
</s:graphicImage>
</rich:column>
</rich:dataTable>
</rich:panel>
I found the solution to my problem. For the column that contains the icon, I put the icon into another <a4j:outputPanel element like this: `
Now, only the action method is executed when clicking on the icon.
Here is the full solution:
<rich:panel headerClass="panelHeader" styleClass="panel">
<f:facet name="header">Header</f:facet>
<rich:dataTable id="myTable" value="#{myModel}" var="k">
<a4j:support event="onRowClick" action="#{myAction.selectItem(k, facesContext.viewRoot.viewId)}"
reRender="myTable"/>
<rich:column>
<f:facet name="header">
<h:outputText value="Normal Column - should be clickable"/>
</f:facet>
<h:outputText value="#{k.name}"/>
</rich:column>
<rich:column >
<f:facet name="header">
<h:outputText value="Only Click on Icon should react to Mouseclick"/>
</f:facet>
<a4j:outputPanel onclick="event.stopPropagation()">
<s:graphicImage value="/img/bin_closed.gif">
<a4j:support event="onclick"
action="#{myAction.deleteItem(k)}"
ajaxSingle="true" limitToList="true"
onsubmit="if(!confirm('Really?')) { return false; }" />/>
</s:graphicImage>
</a4j:outputPanel>
</rich:column>
</rich:dataTable>
</rich:panel>
How can I update a primefaces datatable summary row after submitting a form (dialog)?
The datatable is already updated correctly after some CRUD operation, but the summary row doesn't. I'm using p:remoteCommand to update the summary row when filtering the datatable and it works fine.
The List.xhtml:
<h:form id="TreinamentosListForm">
<p:panel header="#{treinaBundle.ListTreinamentosTitle}" >
<p:remoteCommand name="updateFooterSumCountId" update="datalist:footerSumCountId" />
<p:dataTable id="datalist"
filteredValue="#{treinamentosController.filteredTreinamentos}"
value="#{treinamentosController.items}"
var="item"
rowKey="#{item.id}"
paginator="true"
selectionMode="single"
selection="#{treinamentosController.selected}">
<p:ajax event="filter" process="#form" update="#this" listener="#{treinamentosController.onFilter}" oncomplete="updateFooterSumCountId()" />
<p:ajax event="rowSelect" update=":TreinamentosListForm:createButton :TreinamentosListForm:viewButton :TreinamentosListForm:editButton :TreinamentosListForm:deleteButton :TreinamentosListForm:TreinamentosDataTableContextMenu" listener="#{treinamentosController.resetParents}"/>
<p:ajax event="rowUnselect" update=":TreinamentosListForm:createButton :TreinamentosListForm:viewButton :TreinamentosListForm:editButton :TreinamentosListForm:deleteButton :TreinamentosListForm:TreinamentosDataTableContextMenu" listener="#{treinamentosController.resetParents}"/>
<p:ajax event="rowDblselect" onsuccess="document.getElementById('TreinamentosListForm:viewButton').click();"/>
<p:column sortBy="#{item.id}" filterBy="#{item.id}" style="text-align: right">
<f:facet name="header">
<h:outputText value="#{treinaBundle.ListTreinamentosTitle_id}"/>
</f:facet>
<h:outputText value="#{item.id}"/>
</p:column>
<p:columnGroup id="totalGroup" rendered="true" type="footer" >
<p:row>
<p:column style="text-align:right">
<f:facet name="footer">
<!-- the summary row: -->
<h:outputText id="footerSumCountId" value="#{treinamentosController.sumCountId}" />
</f:facet>
</p:column>
</p:row>
</p:columnGroup>
</p:dataTable>
<f:facet name="header">
<p:commandButton id="createButton" icon="ui-icon-plus" value="#{treinaBundle.Create}" actionListener="#{treinamentosController.prepareCreate}" update=":TreinamentosCreateForm" oncomplete="PF('TreinamentosCreateDialog').show()"/>
<p:commandButton id="viewButton" icon="ui-icon-search" value="#{treinaBundle.View}" update=":TreinamentosViewForm" oncomplete="PF('TreinamentosViewDialog').show()" disabled="#{empty treinamentosController.selected}"/>
<p:commandButton id="editButton" icon="ui-icon-pencil" value="#{treinaBundle.Edit}" update=":TreinamentosEditForm" oncomplete="PF('TreinamentosEditDialog').show()" disabled="#{empty treinamentosController.selected}"/>
<p:commandButton id="deleteButton" icon="ui-icon-trash" value="#{treinaBundle.Delete}" actionListener="#{treinamentosController.delete}" update=":growl,datalist" disabled="#{empty treinamentosController.selected}">
<p:confirm header="#{treinaBundle.ConfirmationHeader}" message="#{treinaBundle.ConfirmDeleteMessage}" icon="ui-icon-alert"/>
</p:commandButton>
</f:facet>
</p:panel>
<ui:include src="/WEB-INF/include/confirmation.xhtml"/>
</h:form>
The Create.xhtml:
<p:dialog id="TreinamentosCreateDlg" widgetVar="TreinamentosCreateDialog" modal="true" resizable="false" appendTo="#(body)" header="#{treinaBundle.CreateTreinamentosTitle}" closeOnEscape="true" >
<h:form id="TreinamentosCreateForm">
<h:panelGroup id="display" rendered="#{treinamentosController.selected != null}">
<p:panelGrid columns="2" columnClasses="column">
<p:outputLabel value="#{treinaBundle.CreateTreinamentosLabel_id}" for="id" />
<p:outputLabel id="id" value="Value automatically generated from database." title="#{treinaBundle.CreateTreinamentosTitle_id}" />
</p:panelGrid>
<p:commandButton actionListener="#{treinamentosController.saveNew}" value="#{treinaBundle.Save}" update="#all,display,:TreinamentosListForm:datalist,:growl" oncomplete="handleSubmit(xhr,status,args,PF('TreinamentosCreateDialog'));">
<p:confirm header="#{treinaBundle.ConfirmationHeader}" message="#{treinaBundle.ConfirmCreateMessage}" icon="ui-icon-alert"/>
</p:commandButton>
<p:commandButton value="#{treinaBundle.Cancel}" onclick="PF('TreinamentosCreateDialog').hide()"/>
</h:panelGroup>
</h:form>
</p:dialog>
Thanks in advance.
After reading the Primefaces 5 documentation, what I did was to invoke (in the Create.xhtml) the Primefaces filter method, referencing through the widgetVar defined in the target datatable (in List.xhtml). Doing so, it triggers my p:remoteCommand, which in its turn, triggers the update for the summary row:
<p:commandButton actionListener="#{treinamentosController.saveNew}" value="#{treinaBundle.Save}" update="#this,display,:TreinamentosListForm:datalist,:growl" oncomplete="handleSubmit(xhr,status,args,PF('TreinamentosCreateDialog'),PF('treinamentosTable').filter());" >
<p:confirm header="#{treinaBundle.ConfirmationHeader}" message="#{treinaBundle.ConfirmCreateMessage}" icon="ui-icon-alert"/>
</p:commandButton>
If someone has a more elegant solution, please share. I had not time
I have a datatable listing some items with several details :
<h:dataTable id="versionInterfaces_datatable"
styleClass="datatable" rowClasses="odd,even"
value="#{versionToolManager.version.interfaces}"
var="lInterface">
<h:column>
<f:facet name="header">Interface Name</f:facet>
<h:commandLink id="versionInterfacesName_columnLink"
value="#{lInterface.name}"
action="#{interfaceManager.consult}">
<f:setPropertyActionListener
target="#{interfaceManager.interfaceEntity}"
value="#{lInterface}" />
</h:commandLink>
<h:outputText id="versionInterfacesName_column" value="#{lInterface.name}" />
</h:column>
<h:column id="interfaceVersions_column">
<f:facet name="header">Interface Version(s)</f:facet>
<ui:repeat value="#{lInterface.versionsInterface}" var="lVersionI"
varStatus="lStatus">
<h:outputText rendered="#{lVersionI.versionsTools.contains(versionToolManager.version)}" value=" #{lVersionI.name} | " />
</ui:repeat>
</h:column>
<h:column>
<f:facet name="header">Interface Description</f:facet>
<h:outputText id="versionInterfacesDescription_column"
value="#{lInterface.description}" />
</h:column>
and then I have a button calling a modal view allowing to add items :
<h:commandButton id="#{id}OpenModal_button"
value="#{openButtonValue}"
onclick="document.getElementById('#{formId}:#{modal_panel}').style.display='block'; return false;" />
<br />
when closing this modal view, I try to "refresh" the datatable to see the items added :
<h:commandButton id="#{id}CloseModal_button"
value="#{closeButtonValue}">
<f:ajax execute="#this"
render="#{renderOnClose} #{formId}:#{modal_panel}" />
</h:commandButton>
But the columns of my datatable are not all updated, the column "Interface Version(s)" is empty for the new lines corresponding to the new items even though when I save, they have been well added.
Do you have any idea ?
the problem is <f:ajax execute="#this" ...
use <f:ajax execute="#all" ...
So I succeed to solve my problem but it wasn't a problem about the syntax but a bad use of the model and beans structure. Without going into details, I was trying to reach data which weren't linked to the corresponding items.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How to ajax-update the p:dataTable from inside the p:dataTable itself?
In my xhtml page i have a dataTable containing object of type Group , and a button to add a new group to the datable and eventually in the database
I'm using a sessionScoped managed Bean , So i need to refresh my datatable rows after adding a new record .
For this i used the update attribute of the command Button component but the datatable is not refreshed and here's the code :
<p:fieldset legend="Groups">
<p:commandButton id="newGroup" value=" New Group" onclick="newGoupDlg.show();"
type="button" update="groupsDataTable"/>
<br/>
<p:dataTable id="groupsDataTable" var="group" value="#
{projectAdminisrationMB.groupsList}"
rowKey="#{group.name}"
rowIndexVar="rowIndex"
binding="#{table}">
<f:facet name="header">
</f:facet>
<p:column id="column2">
<f:facet name="header">
<h:outputText value="Group Name"></h:outputText>
</f:facet>
<p:graphicImage value="/images/group/#{group.name}.gif" />
<h:commandLink action="#{projectAdminisrationMB.showGroupDetails}"
value="#{group.name}">
<f:setPropertyActionListener target="#{projectAdminisrationMB.selectedGroup}"
value="#{group}" />
<f:setPropertyActionListener target="#{projectAdminisrationMB.selectedGroupName}"
value="#{group.name}" />
<f:setPropertyActionListener target="#
{projectAdminisrationMB.selectedGroupDescription}" value="#{group.description}" />
<f:setPropertyActionListener target="#
{projectAdminisrationMB.selectedGroup.dbRowIndex}" value="#{table.rowIndex}" />
</h:commandLink>
</p:column>
<p:column id="column3">
<f:facet name="header">
<h:outputText id="text3" value=" Group Description "></h:outputText>
</f:facet>
<h:outputText value="#{group.description}"></h:outputText>
</p:column>
<f:facet name="footer">
</f:facet>
</p:dataTable>
<p:dialog header="New Group" widgetVar="newGoupDlg" width="750"
showEffect="explode" hideEffect="explode">
<br/> <br/>
<h:outputText value=" New Group : " />
<p:inputText id="newGroupName" value="#
{projectAdminisrationMB.newGroup.name}">
<f:validator validatorId="requiredValidator"></f:validator>
</p:inputText>
<br/> <br/>
<h:outputText value="Group Description :" />
<br/> <br/>
<p:editor id="newGroupDescription" value="#
{projectAdminisrationMB.newGroup.description}" width="600"/>
<br/> <br/>
**<p:commandButton id="ValidateNewGroup" value="Validate"
actionListener="#{projectAdminisrationMB.addNewGroup}"
onclick="newGoupDlg.hide()" update="groupsDataTable" ></p:commandButton>**
<p:commandButton id="CancelNewGroup" value=" Cancel "
onclick="newGoupDlg.hide()"></p:commandButton>
</p:dialog>
<br/> <br/>
</p:fieldset>
Any idea will be apprecited
The most common cause for your problem is that the id of the data table isn't referenced properly.
Check in your browser what the actual id of the data table is.
When your data table is in a container like a form the id of the container is prepended to the id of the data table separated (by default) by a :.
So this:
<h:form id="form">
<p:dataTable id="dt" ...
</h:form>
Will result in the data table having an id of form:dt
When referring to an element inside a container from within another container you need to begin the search from the root. This is done by adding a : in front of the id.
Example:
<h:form id="form">
<p:dataTable id="dt" ...
</h:form>
<h:form id="btnForm">
<p:commandButton update=":form:dt" ...
</h:form>
You can also use binding:
<h:form binding="#{form}">
<p:dataTable id="#{dt}" ...
</h:form>
<h:form id="#{btnForm}">
<p:commandButton update=":#{dt.clientId}" ...
</h:form>