I'm using PrimeFaces 5.1. I have a TabView component in which the tabs are generated dynamically:
<p:tabView scrollable="true"
id="tabView"
dynamic="true" cache="false"
value="#{reportTabBean.tabs}"
var="tab"
activeIndex="#{reportTabBean.activeTab}">
...
</p:tabView>
The content of a tab is wrapped in a <p:outputPanel>. Inside the panel is a mix of plain HTML <table> tags and <ui:____> components. The tab contents make up a report. Each report has clickable elements created by <p:commandLink> that called a method in the manged bean. Here's is the simplified code:
<p:outputPanel id="bcx-scorecard-panel"
rendered="#{ tab['class'].simpleName eq 'CSAE2EScorecardShowTab'}">
<ui:repeat var="LOB"
value="#{tab.scorecardCSAE2E.getLOBs()}">
<table>
<tbody>
<ui:repeat var="metric"
value="#{tab.scorecardCSAE2E.getMetrics(LOB.filter)}">
<ui:fragment rendered="#{metric.type == 'metric'}">
<tr>
<ui:repeat var="dayNum"
value="#{tab.scorecardCSAE2E.daysInMonthIterator()}">
<td>
<ui:fragment
rendered="#{null != metric.getDataFor(dayNum).value and metric.showDogEar(dayNum)}">
<p:commandLink
immediate="true"
update=":dialogExceptionFillWriteOff, :exceptionFillWriteOffForm"
action="#{exceptionWriteBean.populateExceptionPopup(tab.title, LOB.filter, null, metric, tab.scorecardCSAE2E, dayNum)}"
oncomplete="PF('dlgExceptionFillWriteOff').show()">
#{metric.getDataFor(dayNum).value}
</p:commandLink>
</ui:fragment>
</td>
</ui:repeat>
</tr>
</ui:fragment>
</ui:repeat>
</tbody>
</table>
</ui:repeat>
</p:outputPanel>
Clicking the commandLink brings up a model dialog that displays details about that cell. Each cell represents data for a particular day. The problem is the dialog works only for the last tab. I can click each table cell and it'll display the correct data for that day. When I switch to a different tab and click on cells, the populateExceptionPopup method doesn't get called and instead the dialog shows the last pulled data from the other tab.
My beans are view scoped. I'm not sure if it has anything to do with it, but I'm using CDI beans and annotations. Here's one of the beans.
#Named("reportTabBean")
#ConversationScoped
public class ReportTabBean implements Serializable {
...
}
Related
I am new to this Website My issue is related to SelectBooleanCheckbox in primefaces.
Whenever I submit my form, the checkbox gets unchecked.
I am using dynamic tabview.
Here is my xhtml code:-
<h:form id="form" >
<p:panel id="tagsPanel" >
<p:tabView id="tabView" style="background-color:transparent;background-image:none;" var="tabKey" value="#{MBean.Names}"
dynamic="true" >
<p:dataGrid var="appSettingsList" value="#{appSettingsMBean.tabData[tabKey]}" columns="1" styleClass="plainDataGrid">
<h:panelGrid columns="2" border="0" cellspacing="0" cellpadding="0" columnClasses="JspContent12 ,JspContent22" width="100%" >
<p:column escape="false" >
<p:selectBooleanCheckbox value="#{appSettingsList.resultValues.checkboxValue}" style="float:left" id="checkBoxValue"
rendered="#{appSettingsList.currentValues != null and appSettingsList.currentValues.size() > 0 and
appSettingsList.displayType.equalsIgnoreCase('single') and appSettingsList.dataType.equalsIgnoreCase('boolean')}">
</p:selectBooleanCheckbox>
</p:column>
</h:panelGrid>
</p:dataGrid>
</p:panel>
<p:panel border="0" id="buttonRow" style="text-align:center;border-width:0;border-style:none;background-image:none;" >
<p:commandButton value="Save" id="save" actionListener="#{MBean.saveSettings()}" ajax="false" style="width:130px" />
</p:panel>
</h:form>
The checkboxes remain checked when tabs are changed and save btn is clicked
But,when only the save btn is clicked,it gets unchecked
Any help will be appreciated...
Here,
<p:commandButton ... ajax="false" />
Ajax is turned off. Thus a full page refresh is performed after submitting the form. That the checkbox got unchecked suggests that the bean doesn't properly keep its state, or that you're performing business logic in a getter method, which causes it to return a fresh new model everytime instead of the one holding the submitted values.
You've 2 options:
Just use ajax. I.e. get rid of ajax="false". If you intend to update certain parts of the view on submit, then just specify update attribute accordingly.
Make sure that your bean doesn't mess with the state or getters.
I have a problem about reference in a form.
In the same form, I have a
- table generated with tags
- a panel, allowing user to edit cell content (with multiple inputs and informations)
I use a <p:commandButton> with a <f:setPropertyActionListener> to store the cell value and refresh the detail's panel. This part as no problem.
When the user's edit ends, he save its changes by clicking on "save" button in the detail panel. I'd like to refresh only the previously selected cell and not the whole table.
So I had a to save the Component.clientId and put a "renderer=xxx" on the button to be sure the id is not null.
But it always throws javax.faces.FacesException...
<table class="measureTable" id="measureTable">
<!-- header -->
<tbody ... >
<tr class="ui-column-title">
<th ...> ...</th>
<ui:repeat var="columnHeader" value="#{managedBean.columnModels}" id="columnHeaders" >
<th ><p:outputLabel value="#{columnHeader.name}" /></th>
</ui:repeat>
</tr>
<!-- datas -->
<ui:repeat var="vLine" value="#{managedBean.roundvLines}" id="lines" >
<tr>
<td >
<p:panel styleClass="cellPanel">
<p:outputLabel value="#{vLine.id}" styleClass="ui-column-header" />
</p:panel>
</td>
<ui:repeat var="vCell" value="#{vLine.cells}" id="cells">
<td>
<p:commandButton styleClass="cellPanel" value="#{vCell.value}" update=":formControl:detailPanel" >
<f:setPropertyActionListener value="#{vCell}" target="#{managedBean.currentCell}" />
<f:setPropertyActionListener value="#{component.clientId}" target="#{managedBean.currentComponentId}" />
</p:commandButton>
</td>
</ui:repeat>
</tr>
</ui:repeat>
</tbody>
</table>
<p:panel id="detailPanel">
<p:panel rendered="#{!empty managedBean.currentCell}" styleClass="panelWithoutBorder">
<ui:param name="definition" value="#{managedBean.currentCell.measureDefinition}"/>
<ui:param name="measure" value="#{managedBean.currentCell}"/>
<p:panel id="detailValue" header="Valeur">
<!-- NUM -->
<p:keyboard value="#{measure.value}" keypadOnly="true"
rendered="#{definition.codeTypeSais == 1}" />
<!-- STR -->
<p:keyboard value="#{measure.value}"
rendered="#{definition.codeTypeSais == 2}"/>
...
</p:panel>
...
<p:panel>
<p:commandButton value="refresh" update=":formControl:specimen:0"
rendered="#{!empty managedBean.currentComponentId}"></p:commandButton>
</p:panel>
</p:panel>
</p:panel>
GRAVE: javax.faces.FacesException: Cannot find component with expression ":formControl:lines:0:cells:0:j_idt20" referenced from "j_idt36".
at org.primefaces.expression.SearchExpressionFacade.resolveComponentInternal(SearchExpressionFacade.java:422)
at org.primefaces.expression.SearchExpressionFacade.resolveComponentForClient(SearchExpressionFacade.java:200)
at org.primefaces.expression.SearchExpressionFacade.resolveComponentsForClient(SearchExpressionFacade.java:147)
at org.primefaces.util.AjaxRequestBuilder.addExpressions(AjaxRequestBuilder.java:92)
at org.primefaces.util.AjaxRequestBuilder.update(AjaxRequestBuilder.java:85)
at org.primefaces.renderkit.CoreRenderer.buildAjaxRequest(CoreRenderer.java:356)
at org.primefaces.component.commandbutton.CommandButtonRenderer.buildRequest(CommandButtonRenderer.java:123)
...
I allready read following topics:
use-an-el-expression-to-pass-a-component-id-to-a-composite-component-in-jsf
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
I can't use binding because components are auto generated and too many.
The component already existe because the page haven't changed.
I tried too update only the top/left cell, using its id gaven by the stacktrace but an Exception is still throwed.
It only works when I update the whole form (update=":formControl")... :S
how can I solve it?
PS: I used primefaces but the final terminal is an old company android 2.3.4 with default browser and lots of stuff doesn't work so i have to do it manually.
I fixed this 2 weeks ago in PrimeFaces with some other improvements on the SearchExpressionFramework.
Please try a trunk build - if it doesn't work, create a an issue please + full example.
I 'm using the tag ui:repeat to display a list of pictures and their titles.
My code is:
<p:dialog id="idSchemaDlg5" widgetVar="schemaDlg" position="10" resizable="true" modal="true" header="Schéma des composants">
<h:panelGrid columns="1">
<ui:repeat value="#{imageStreamer.pictureNamesList}" var="imageName" >
<h:panelGrid columns="#{imageStreamer.pictureNamesList.size()}">
<p:graphicImage value="#{imageStreamer.image}" >
<f:param name="pictureName" value="#{imageName}" />
</p:graphicImage>
<h:outputText value="#{imageName}"/>
</ui:repeat>
</h:panelGrid>
</p:dialog>
I would to display the list of pictures horizontally but the list of pictures with this code was vertically displayed.
Any help is welcome.
I would to have this structure in output <table><tbody><tr><td><img1/><title1/></td><td><img2/><title2/></td><img3/><title3/><td></td></tr></table>
The <ui:repeat> inside <h:panelGrid> won't generate physically multiple table cells. It will generate only one table cell. In fact, each immediate child UI component of <h:panelGrid> counts as a single table cell. The <ui:repeat> is an UI component.
You need <c:forEach> instead. It's a taghandler and runs during building JSF component tree instead of during generating HTML output. It generates physically multiple JSF components, in contrary to <ui:repeat> which represents physically one JSF component which is reused everytime during generating HTML output.
<h:panelGrid columns="#{imageStreamer.pictureNamesList.size()}">
<c:forEach items="#{imageStreamer.pictureNamesList}" var="imageName">
<h:panelGroup>
<p:graphicImage value="#{imageStreamer.image}">
<f:param name="pictureName" value="#{imageName}" />
</p:graphicImage>
<h:outputText value="#{imageName}"/>
</h:panelGroup>
</c:forEach>
</h:panelGrid>
(note that you need to wrap the image and the text in a <h:panelGroup> to represent a single table cell)
Or, if you insist in using <ui:repeat>, then you have to write down the desired HTML output yourself.
<table>
<tbody>
<tr>
<ui:repeat value="#{imageStreamer.pictureNamesList}" var="imageName">
<td>
<p:graphicImage value="#{imageStreamer.image}">
<f:param name="pictureName" value="#{imageName}" />
</p:graphicImage>
<h:outputText value="#{imageName}"/>
</td>
</ui:repeat>
</tr>
</tbody>
</table>
See also:
JSTL in JSF2 Facelets... makes sense?
create table columns dynamically in JSF
you must change the order of the h:panelGrid and p:graphicImage. because you repeat the creation of the h:panelGrid with size() as number of columns. your code becomes:
<p:dialog id="idSchemaDlg5" widgetVar="schemaDlg" position="10" resizable="true" modal="true" header="Schéma des composants">
<h:panelGrid columns="#{imageStreamer.pictureNamesList.size()}">
<ui:repeat value="#{imageStreamer.pictureNamesList}" var="imageName" >
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td> <p:graphicImage value="#{imageStreamer.image}" >
<f:param name="pictureName" value="#{imageName}" />
</p:graphicImage>
</td>
</tr>
<tr>
<td ><h:outputText value="#{imageName}"/></td>
</tr>
</table>
</ui:repeat>
</h:panelGrid>
</p:dialog>
I need to show a list of auction items. When a user clicks on a Bid button next to each item, I'd like to have ajax open a bid form right under this auction item. So I'm going with a ui:repeat and a f:ajax as shown below, but when I go to the page all the auction items have the bid component open next to them. And clicking any of the buttons doesn't do anything. This is the code (with the bid form simplified to just an outputText:)
<h:form>
<table border="1">
<ui:repeat var="parcel" varStatus="status" value="#{auctionsViewBean.parcels}">
<tr>
<td><h:commandButton value="Bid" action="nothing">
<f:ajax render="bidView"/>
</h:commandButton></td>
<td>#{status.index + 1}</td>
<td>#{parcel.a}</td>
<td>#{parcel.b}</td>
<td>#{parcel.c}</td>
</tr>
<tr><td><h:outputText id="bidView" value="#{auctionsViewBean.showBidViewForParcel(parcel)}">Some text</h:outputText></td></tr>
</ui:repeat>
</table>
</h:form>
What am I doing wrong? And how can I specify only the bid component related to the clicked auction item?
If I understand you correctly, you want to initially hide the bidView until the button is pressed? You can do it by giving it a rendered attribute and put it in another component which can be referenced by <f:ajax>. You only need to rearrange the action method and checking logic.
<h:commandButton value="Bid" action="#{auctionsViewBean.addBidView(parcel)}">
<f:ajax render="bidView" />
...
<h:panelGroup id="bidView">
<h:panelGroup rendered="#{auctionsViewBean.showBidView(parcel)}">
...
</h:panelGroup>
</h:panelGroup>
with something like this:
public void addBidView(Parcel parcel) {
bidViews.put(parcel, new BidView());
}
public boolean isShowBidView(Parcel parcel) {
return bidViews.containsKey(parcel);
}
p:filedownload from p:datatable with ViewScoped managed bean wont work. It calls the methods prepareFile and getFile twice. In first call of the methods I mentioned it sets the first file from the table, and in the second call of the methods it sets the right file, but it always downloads only the first one and the second one is never downloaded.
Why does it call twice? Why does it set the first file from the table? Any ideas?
Here's my code:
<p:dataTable id="offer_attachment_datatable"
widgetVar="offer_attachment_datatable"
var="attachment"
value="#{offerBean.offerAttachments}">
<p:column>
<f:facet name="header"/>
<p:commandLink ajax="false" actionListener="#{offerBean.prepareFile(attachment)}" title="#{attachment.name}">
<p:graphicImage value="/resources/themes/navigator_b2e/images/drive-download.png" />
<p:fileDownload value="#{offerBean.file}"/>
</p:commandLink>
</p:column>
</p:dataTable>
and in managed bean (simplified):
private StreamedContent file;
private InputStream stream;
public void prepareFile(OfferAttachment attachment){
System.out.println("Attachment: "+attachment.getName());
stream = new ByteArrayInputStream(attachment.getAttachment());
file = new DefaultStreamedContent(stream, "text/plain", attachment.getName());
stream = null;
}
public StreamedContent getFile() {
System.out.println("File: "+file.getName());
return file;
}
public void setFile(StreamedContent file) {
this.file = file;
}
So, I made a workaround with a simple p:confirmDialog where I extracted the problematic ajax=false command link, so I select the attachment by clicking it in p:datatable and execute the download from the p:confirmdialog.
I had the same problem in 2.2.1. I found the solution by replacing p:commandLink to p:commandButton with the same attributes. Seems that it is a bug related with behavior of the commandLink component
Ok, guys, so I made a workaround with a simple p:confirmDialog where I extracted the problematic ajax=false command link, so I select the attachment by clicking it in p:datatable and execute the download from the p:confirmdialog.
The solution that worked for me was to replace "p:datatable" with "ui:repeat(facelets) and table", like this:
<table role="grid">
<thead>
<tr role="row">
<th>File Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<ui:repeat value="#{downloadFileBean.files}" var="f">
<tr role="row">
<td><h:outputText value="#{f.name}" /></td>
<td>
<p:commandLink id="download" ajax="false">
<h:outputText value="Download" />
<p:fileDownload value="#{downloadFileBean.file}" />
<f:param name="fileName" value="#{f.name}" />
</p:commandLink>
</td>
</tr>
</ui:repeat>
</tbody>