I have a bean:
#ManagedBean
#SessionScoped
public class MainTable
{
static List<MainTableRow> rows;
public MainTable()
{
rows = new ArrayList<>();
}
public static boolean addRow(MainTableRow mainTableRow)
{
return rows.add(mainTableRow);
}
public List<MainTableRow> getRows()
{
return rows;
}
public void setRows(List<MainTableRow> rows)
{
MainTable.rows = rows;
}
}
And my xhtml page is:
<h:body>
<h3>Query Modeling Tool - Select Excel file</h3>
<h:form>
<p:fileUpload
fileUploadListener="#{fileUploadController.handleFileUpload}"
mode="advanced" dragDropSupport="false" update="messages"
sizeLimit="10000000" fileLimit="3" allowTypes="/(\.|\/)(xls)$/"
style="font-size: 14px" />
<p:growl id="messages" showDetail="true" />
<p:dataTable id="dataTable" var="mainTableRow"
value="#{mainTable.rows}" style="font-size: 14px">
<f:facet name="header">Main Table</f:facet>
<p:column sortBy="" headerText="Index">
<h:outputText value="#{mainTableRow.index}" />
</p:column>
<p:column sortBy="" headerText="Query">
<h:outputText value="#{mainTableRow.query}" />
</p:column>
<p:column sortBy="" headerText="S1">
<h:outputText value="#{mainTableRow.s1}" />
</p:column>
<p:column sortBy="" headerText="S2">
<h:outputText value="#{mainTableRow.s2}" />
</p:column>
<p:column sortBy="" headerText="S3">
<h:outputText value="#{mainTableRow.s3}" />
</p:column>
<p:column sortBy="" headerText="S9">
<h:outputText value="#{mainTableRow.s9}" />
</p:column>
<p:column sortBy="" headerText="Uygunluk">
<h:outputText value="#{mainTableRow.uygunluk}" />
</p:column>
<p:column sortBy="" headerText="Kural">
<h:outputText value="#{mainTableRow.kural}" />
</p:column>
<p:column sortBy="" headerText="Kaynak">
<h:outputText value="#{mainTableRow.kaynak}" />
</p:column>
<p:column sortBy="" headerText="Query Type">
<h:outputText value="#{mainTableRow.queryType}" />
</p:column>
<p:column sortBy="" headerText="User Intent">
<h:outputText value="#{mainTableRow.userIntent}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>
"rows" in MainTable is filled by another class, after uploading a file.
After uploading I want to refresh dataTable without clicking any button.
How can I do it?
It can be solved by one of the following points:
1. <p:fileUpload> has an attribute update that is used to ajax-update the components with a specified list of comma/space-separated ids, so you need to add id of your data table to that attribute:
<p:fileUpload ... update="messages dataTable" />
2. When a file has been uploaded, the table can also be updated programmatically in your action method:
RequestContext context = RequestContext.getCurrentInstance();
context.addPartialUpdateTarget("<path_to_your_table>");
See also:
jsf/primfaces update ui components from server event
Related
I am trying to set some information in dialogue box when the search button is clicked but the problem I am facing is that f:setPropertyActionListener is not setting the target value in the backing bean so when the popup comes its empty.
Dialogue box looks like this :
<h:form id="form">
<p:fieldset legend="Saved Branches" style="margin-bottom: 30px;">
<p:dataTable id="branches" var="branch" value="#{branchOnBoarding.savedBranches}">
<f:facet name="header">
Branch Information
</f:facet>
<p:column headerText="Branch Name">
<h:outputText value="#{branch.branchName}" />
</p:column>
<p:column headerText="Branch Code">
<h:outputText value="#{branch.branchCode}" />
</p:column>
<p:column headerText="Building">
<h:outputText value="#{branch.building}" />
</p:column>
<p:column headerText="Street">
<h:outputText value="#{branch.street}" />
</p:column>
<p:column headerText="City">
<h:outputText value="#{branch.city}" />
</p:column>
<p:column headerText="State">
<h:outputText value="#{branch.state}" />
</p:column>
<p:column headerText="Country">
<h:outputText value="#{branch.country}" />
</p:column>
<p:column style="width:32px;text-align: center">
<p:commandButton update=":form:branchDetail" oncomplete="PF('branchDialog').show()" icon="ui-icon-search" title="View">
<f:setPropertyActionListener value="#{branch}" target="#{branchOnBoarding.selectedBranch}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Branch Info" widgetVar="branchDialog">
<p:outputPanel id="branchDetail" style="text-align:center;">
<p:panelGrid columns="2" rendered="#{not empty branchOnBoarding.selectedBranch.branchName}" columnClasses="label,value">
<h:outputText value="Branch Name:" />
<h:outputText value="#{branchOnBoarding.selectedBranch.branchName}" />
<h:outputText value="Branch Code:" />
<h:outputText value="#{branchOnBoarding.selectedBranch.branchCode}" />
<h:outputText value="Building:" />
<h:outputText value="#{branchOnBoarding.selectedBranch.building}" />
<h:outputText value="Street:" />
<h:outputText value="#{branchOnBoarding.selectedBranch.street}" />
<h:outputText value="City:" />
<h:outputText value="#{branchOnBoarding.selectedBranch.city}" />
<h:outputText value="State:" />
<h:outputText value="#{branchOnBoarding.selectedBranch.state}" />
<h:outputText value="Country:" />
<h:outputText value="#{branchOnBoarding.selectedBranch.country}" />
</p:panelGrid>
</p:outputPanel>
</p:dialog>
</p:fieldset>
Code for backing bean looks like this :
#Component(value="branchOnBoarding")
#ManagedBean
#SessionScoped
#SpringScopeView
public class BranchOnBoarding implements Serializable{
private BranchUI branchUI = new BranchUI();
private List<Branch> savedBranches = new ArrayList<>();
private Branch selectedBranch;
public Branch getSelectedBranch() {
return selectedBranch;
}
public void setSelectedBranch(Branch selectedBranch) {
this.selectedBranch = selectedBranch;
}
public List<Branch> getSavedBranches() {
savedBranches = branchDao.findAll();
//for(Branch b:savedBranches)
//System.err.println(b.getBranchName());
return savedBranches;
}
public void setSavedBranches(List<Branch> savedBranches) {
this.savedBranches = savedBranches;
}
}
Dialogue box looks like this :
In my cell edit event in my backing bean, if the cell value is changed I want to update the value of another column as well of the datatable. The value is getting correctly set in my list object but is not getting reflected in my datatable. I tried updating using the datatable using RequestContext as well, but still the list is not getting refreshed. What am I doing wrong? Should I call any row event for this change?
Code snippet :
Bean
#Named("editView")
#ViewScoped
public class EditTableView implements Serializable {
private List<Cars> carList;
private List<String> brands;
#PostConstruct
public void init() {
brands = new ArrayList<String>();
brands.add("BMW");
brands.add( "Mercedes");
brands.add("Volvo");
brands.add("Audi");
brands.add("Renault");
brands.add("Fiat");
brands.add("Volkswagen");
brands.add("Honda");
brands.add("Jaguar");
brands.add( "Ford");
brands.add("Maruti Suzuki");
carList = new ArrayList<Cars>();
modifiedList = new ArrayList<Cars>();
Cars car =new Cars();
car.setCarId(1);
car.setBrand("BMW");
car.setColor("Grey");
car.setModelNumber("2323");
car.setSelfDriven("Y");
car.setYear("1980");
car.setStatus("");
carList.add(car);
}
public void onCellEdit(CellEditEvent event) {
int rowIndex = event.getRowIndex();
Cars car = null;
LOGGER.info("Car Edited"+rowIndex);
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
DataTable carTable = (DataTable) event.getSource();
String index = carTable.getClientId(FacesContext.getCurrentInstance());
LOGGER.info(index);
if(newValue != null && !newValue.equals(oldValue)) {
LOGGER.info("Cell Changed Old: " + oldValue + ", New:" + newValue);
car=carList.get(rowIndex);
carList.get(event.getRowIndex()).setStatus("Changed");
modifiedList.add(car);
}
}
}
xhtml
<h:form id="cellEditForm">
<p:dataTable id="cars" var="car" value="#{editView.carList}"
editable="true" editMode="cell" widgetVar="cellCars">
<f:facet name="header">Cell Editing</f:facet>
<p:ajax event="cellEdit" listener="#{editView.onCellEdit}"
update=":cellEditForm:cars" />
<p:column headerText="Id">
#{car.carId}
</p:column>
<p:column headerText="Model Name" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.modelNumber}" />
</f:facet>
<f:facet name="input">
<p:inputText id="modelInput" value="#{car.modelNumber}"
style="width:96%" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Year" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.year}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{car.year}" style="width:96%" label="Year" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Brand" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.brand}" />
</f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{car.brand}" style="width:100%">
<f:selectItems value="#{editView.brands}" var="man"
itemLabel="#{man}" itemValue="#{man}" />
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Self Driven" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.selfDriven}" />
</f:facet>
<f:facet name="input">
<p:inplace>
<p:inputText value="#{car.selfDriven}" />
</p:inplace>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Color" style="background-color:yellow">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{car.color}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{car.color}" style="width:96%" label="Color" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column>
<h:outputText value="#{car.status}" id="statusLabel"></h:outputText>
</p:column>
</p:dataTable>
</h:form>
I used jquery eventually. Got the index of the updated row and called jquery function from my bean.
RequestContext requestContext = RequestContext.getCurrentInstance();
String call = "updateCell(" + event.getRowIndex() + ")";
requestContext.execute(call);
Jquery code
function updateCell(i) {
var index = "cellEditForm:cars:"+i+":statusLabel";
document.getElementById(index).innerHTML="Changed";
}
OmniFaces has a great util for this, called 'Ajax'
A StackOverflow post about this shows how to use it: How to use OmniFaces Ajax.updateColumn() or Ajax.updateRow() via p:ajax
Update form not table or put table in panel and update panel.
to be safe
<h:form id="cellEditForm">
<p:panel id="something" styleclass="pero">
<p:dataTable id="cars
update="#(.pero)"
be sure to put id on panel because class update will search for that id and use it. This solution is because i don't know rest of the code and it is one that will work on any code.
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
I have a dataTable that gets populated with rows. On clicking on a row, the include webpage updates with new infomation. Unfortunately, the ajax event only fires once. Here's the code:
.xhtml
<h:form id="form">
<f:loadBundle basename="com.company.messages" var="msgs" />
<p:tabView id="tabView" effect="fade" effectDuration="fast">
<p:tab title="#{msgs.activeInterestPlansTab}">
<p:dataTable var="plan" value="#{interestPlanReports.activePlans}"
rowKey="#{plan.planNumber}"
selection="#{interestPlanReports.selectedPlan}"
selectionMode="single">
<p:ajax event="rowSelect" listener="#{interestPlanReports.onRowSelect}"
update=":form:tabView:tiers" oncomplete="interestPlanPanel.show()" />
<p:ajax event="rowUnselect" listener="#{interestPlanReports.onRowUnselect}"
update=":form:tabView:tiers" oncomplete="interestPlanPanel.show()"/>
<p:column headerText="Plan Number">
#{plan.planNumber}
</p:column>
<p:column headerText="Description">
#{plan.planDescription}
</p:column>
<p:column headerText="Base Plan" >
#{plan.basePlanNumber}
</p:column>
<p:column headerText="Base">
#{plan.interestRateCodeReadable}
</p:column>
<p:column headerText="Base Rate">
<!-- #{plan.baseRatePlan} -->
TODO
</p:column>
<p:column headerText="Premium">
TODO
</p:column>
<p:column headerText="Effective Date">
<h:outputText value="#{plan.effectiveDate}" >
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:outputText>
</p:column>
<p:column headerText="Expiration Date">
<h:outputText value="#{plan.expirationDate}" >
<f:convertDateTime pattern="MM/dd/yyyy" />
</h:outputText>
</p:column>
</p:dataTable>
<p:panel id="tiers" widget="interestPlanPanel">
<ui:include src="/interestplansearch/interestPlanDetail.xhtml">
<ui:param name="interestPlan" value="#{interestPlanReports.selectedPlan}"/>
</ui:include>
</p:panel>
</p:tab>
bean
public InterestPlan getSelectedPlan() {
if (selectedPlan == null)
{
selectedPlan = activePlans.get(0);
}
return selectedPlan;
}
public void setSelectedPlan(InterestPlan selectedPlan) {
this.selectedPlan = selectedPlan;
}
public void onRowSelect(SelectEvent event)
{
setSelectedPlan( (InterestPlan)event.getObject() );
}
public void onRowUnselect(UnselectEvent event) {
setSelectedPlan( (InterestPlan)event.getObject() );
}
Not sure what I'm missing. I appreciate any feedback. Thanks
UPDATE: Removing oncomplete from both rowSelect and rowUnselect fixes the issue on FireFox. However, on IE the first row select updates the panel. Any additional selects reverts to the original selection (update not row)
I would like to update a component showing data related to the info displayed in the current page of a primefaces dataTable but I couldn't find any info about intercepting ajax events like
onRowsPerPageChange or onPageChanged.
Is there any way to do that?
Using primefaces 3.0.M3 and Glassfish 3.1
Here is my table. The component I want to update is another dataTable inside the footer of the first one:
<p:dataTable id="timbrature_dt"
value="#{timbratureMBean.dataModel}"
paginator="true"
rows="12"
lazy="true"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
rowsPerPageTemplate="6,12,24"
currentPageReportTemplate="#{msgs.pagina} {currentPage} #{msgs.of} {totalPages}"
var="tdett"
widgetVar="ttable"
selection="#{timbratureMBean.selezione}"
selectionMode="single">
<p:ajax event="rowSelect" listener="#{timbratureMBean.onRowSelect}"
update="display :timbrature_dt:giustificativi_dt"
oncomplete="timbDialog.show()" />
<f:facet name="header">
<h:panelGrid columns="1" columnClasses="columnclass-noborders">
<p:outputPanel>
<h:outputText value="#{msgs.dal}: " />
<p:calendar value="#{timbratureMBean.daData}"
pattern="dd/MM/yyyy"
locale="it"
showButtonPanel="true"
navigator="true"
mindate="01/01/2003"
maxdate="#{timbratureMBean.oggi}">
<p:ajax event="dateSelect" listener="#{timbratureMBean.dataChangeListener}"
update="timbrature_dt :timbrature_dt:giustificativi_dt" />
</p:calendar>
<h:outputText value=" #{msgs.al}: " />
<p:calendar value="#{timbratureMBean.aData}"
pattern="dd/MM/yyyy"
locale="it"
showButtonPanel="true"
navigator="true"
mindate="01/01/2003"
maxdate="#{timbratureMBean.oggi}">
<p:ajax event="dateSelect" listener="#{timbratureMBean.dataChangeListener}"
update="timbrature_dt :timbrature_dt:giustificativi_dt" />
</p:calendar>
</p:outputPanel>
<h:outputText value="#{msgs.timbrature}"/>
</h:panelGrid>
</f:facet>
<p:column>
<f:facet name="header">
#{msgs.data_comp}
</f:facet>
<amp:outputData value="#{tdett.sDtComp}"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.data_reale}
</f:facet>
<amp:outputData value="#{tdett.sDtTimb}"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.terminale}
</f:facet>
<h:outputText value="#{tdett.nrTer}"/>
</p:column>
<p:column filterBy="#{tdett.eU}" filterOptions="#{timbratureMBean.euOptionList}">
<f:facet name="header">
#{msgs.verso}
</f:facet>
<h:panelGroup>
<h:outputText value="#{msgs.entrata}" rendered="#{tdett.eU == 'E'}"/>
<h:outputText value="#{msgs.uscita}" rendered="#{tdett.eU == 'U'}"/>
</h:panelGroup>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.ora_valida}
</f:facet>
<h:outputText value="#{tdett.oraValida}"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.ora_reale}
</f:facet>
<h:outputText value="#{tdett.oraReale}"/>
</p:column>
<f:facet name="footer">
<p:dataTable id="giustificativi_dt"
value="#{timbratureMBean.dataList}"
var="gius"
widgetVar="gtable">
<f:facet name="header">
<h:panelGrid columns="1" columnClasses="columnclass-noborders">
<h:outputText value="#{msgs.giustificativi}"/>
</h:panelGrid>
</f:facet>
<p:column>
<f:facet name="header">
#{msgs.voce}
</f:facet>
<h:outputText value="#{gius.voce}"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.dal}
</f:facet>
<amp:outputData value="#{gius.sDtIGius}"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.al}
</f:facet>
<amp:outputData value="#{gius.sDtFGius}"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.nr_giorni}
</f:facet>
<h:outputText value="#{gius.nrGiorni}"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.ora_inizio}
</f:facet>
<amp:outputNvl value="#{gius.oraIGius}" nullval="-"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.ora_fine}
</f:facet>
<amp:outputNvl value="#{gius.oraFGius}" nullval="-"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.nr_ore}
</f:facet>
<amp:outputNvl value="#{gius.nrOre}" nullval="-"/>
</p:column>
<p:column>
<f:facet name="header">
#{msgs.nr_minuti}
</f:facet>
<amp:outputNvl value="#{gius.nrMinuti}" nullval="-"/>
</p:column>
</p:dataTable>
</f:facet>
</p:dataTable>
<p:dialog header="Info" widgetVar="timbDialog" resizable="false"
width="200" showEffect="clip" hideEffect="clip">
<h:panelGrid id="display" columns="2" cellpadding="4">
<h:outputText value="Data:" style="font-weight: bold"/>
<amp:outputData value="#{timbratureMBean.selezione.sDtComp}" />
<h:outputText value="Pausa pranzo ridotta: " style="font-weight: bold"/>
<h:outputText value="#{timbratureMBean.gestPausaPranzo}" />
<h:outputText value="Timbratura non allineata: " style="font-weight: bold"/>
<h:outputText value="#{timbratureMBean.timbNonAllineate}" />
</h:panelGrid>
</p:dialog>
Hou,
there is an event for changing a page, see here
http://cagataycivici.wordpress.com/2011/06/10/datatable-hooks/
<p:datatable paginator="true" rows="10" value="#{bean.items}" var="item">
<p:ajax event="page" listener="#{bean.onPaginate}" update="othercomponents" oncomplete="alert('done')"... />
...
though I am still looking for an event for onChangeRows
but, my current problem is only storing user choices, in fact that page event solves storing both on what page I am and how many rows are selected. If onPaginate implements in this way:
public void onPaginate(PageEvent event){
logger.info("I am on page:"+event.getPage());
logger.info("Rows per page set:"+((org.primefaces.component.datatable.DataTable)event.getSource()).getRows());
}
You can see what page you are on and how many rows are selected. And this event is triggered both when you change a page or change how many rows shown.
My solution is using Primefaces 5.2.x.
I found a pretty easy way to implement this, one of the problems I had with udik's solution was that when the onPaginate() method was called, it didn't have the newest selected value.
So here's what I did to make sure you always had the latest value and could save/load it to the database or a cookie or something (we save to a cookie).
<p:dataTable
.....
paginator="true"
paginatorPosition="bottom"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
currentPageReportTemplate="Total records: {totalRecords}, showing page {currentPage} of {totalPages}"
rowsPerPageTemplate="25,50,100"
rows="#{controller.rowsPerPage}"
.....
>
.....
<p:ajax event="page" oncomplete="rowsPerPageUpdate()" />
.....
</p:dataTable>
<p:remoteCommand name="rowsPerPageUpdate" actionListener="#{controller.onPaginate}" />
and then our controller looks like this:
#Dependent
#Named
public class TableController implements Serializable {
private String rowsPerPage = "25"; //default value
.....
public void onPaginate() {
//save to the cookie
}
.....
}
Basically the magic happens in the remoteCommand, which will fire after the ajax event to insure that controller.rowsPerPage has been properly updated.