c:forEach + Data table multiple row selection crashes old selected values - jsf

i use JSF 2.0 and primefaces 4.0
my JSF code :
<c:forEach items="#{materielbean.materielist}" var="list" >
<p:dataTable var="car" value="#{materielbean.listeitemsmaterielbyidmateriel(list.idmateriel)}" rowKey="#{car.iditemsmateriel}"
selection="#{fournisseurbean.selectedItemsMateriel}" selectionMode="multiple" style="width : 664px; ">
<f:facet name="header">
#{list.nommateriel}
</f:facet>
<p:column headerText="designation">
#{car.designation}
</p:column>
<p:column headerText="Unité">
#{car.unite}
</p:column>
</p:dataTable>
</c:forEach>
and the used function
listeitemsmaterielbyidmateriel(list.idmateriel)
is defined like this
public List listeitemsmaterielbyidmateriel(int i){
return itemmaterielDAO.DisplayItemsMaterielDAOselonmMateriel(i);
}
And finally this is the DAO code
public List DisplayItemsMaterielDAOselonmMateriel(int idmateriel )
{
Query q = em.createQuery("select LIM from ItemsMateriel LIM inner join LIM.materiel where LIM.materiel.idmateriel= :idmateriel");
q.setParameter("idmateriel", idmateriel);
List l = new ArrayList();
l= q.getResultList();
return l ;
}
when i run this code , i got no errors , but selection="#fournisseurbean.selectedItemsMateriel}"
returns only the values of the final iteration(final datatable) , it's because in every iteration the list crashes old selected objects and put new selected objects , how can i do to prevent this ??

It's dangerous to mix JSTL core tags with JSF- and/or *Faces tags. Basically JSTL tag handler get executed during view build time, while JSF UIComponents get executed during view render time. See the very good answer at "JSTL in JSF2 Facelets… makes sense?"
Have you already tried to solve the issue using Facelets ui:repeat component?

Well sorry for late , but i discovored that the solution is easier than i thought :
First create a new list
List<ItemsMateriel> Tampon = new ArrayList<ItemsMateriel>();
Second modify the setter to :
public void setSelectedItemsMateriel(List<ItemsMateriel> selectedItemsMateriel) {
Tampon.addAll(selectedItemsMateriel);
this.selectedItemsMateriel = selectedItemsMateriel;
}
And finally to use the new list (Tampon) and you'll find all selected objects

Related

Non rendered p:dataTable ends up in pe:exporter PDF

I have 2 dataTables:
<p:dataTable id="tbl1" var="prop1" value="#{bean.prop1}" rendered="#{bean.listP1.size() != 0}">
// ...
</p:dataTable>
and
<p:dataTable id="tbl2" var="prop2" value="#{bean.prop2}" rendered="#{bean.listP2.size() != 0}">
// ...
</p:dataTable>
On XHTML page, after some action, I got the correct result depending on the size of both listP1 and listP2.
My problem is after clicking on export button
<h:commandLink>
<p:graphicImage value="/resources/icons/download.png" style="width : 35px; height:35px"/>
<pe:exporter type="pdf" target="tbl1, tbl2" fileName="SurveyResults"/>
</h:commandLink>
I got wrong result : I got the two tables instead of one because one of them is with size = 0
Have you please any idea about solving that?
Prior to version 8, the pe:exporter does not care whether the data tables you provide are rendered or not, see https://github.com/primefaces-extensions/primefaces-extensions.github.com/issues/757
If you are not on version 8 yet, you can use EL to create a dynamic value for the target attribute though. For example:
<pe:exporter type="pdf"
target="#{empty bean.listP1 ? '' : 'tbl1'}#{empty bean.listP1 or empty bean.listP2 ? '' : ','}#{empty bean.listP2 ? '' : 'tbl2'}"
fileName="SurveyResults"/>
As these expressions are a bit hairy, you might want to create a method in your bean which creates a target string and do:
<pe:exporter type="pdf"
target="#{bean.exporterTargets}"
fileName="SurveyResults"/>
And in your bean for example:
public String getExporterTargets() {
return Stream.of(listP1.isEmpty() ? null : "tbl1",
listP2.isEmpty() ? null : "tbl2")
.filter(Objects::nonNull)
.collect(Collectors.joining(","));
}

Primefaces won't call setter on ManagedBean

I'm in the middle of building a web application (Spring 4, Primefaces 5.1 and JPA).
While one of my xhtml-pages has no problems working with its ManagedBean, the others won't really work. To be more specific, the UI input components (like inputText) won't call any setters from the managed Beans.
I've already run my Tomcat (8) on debug mode, which showed me that the page calls the get-methods, but no set-methods at all. If I try to persist something, all values are null (or 0, in case of an int-value). (it even persists an object into the database with all values null, though I have declared some #NotNull constraints which should be taken to the database configuration via JPA)
So, question is: How can I make my inputFields work with the fields of my ManagedBean? (Eclipse also shows me in the editor, that theoretically, the connection to the fields is there, it knows the managed bean, the field and the get-/set-methods)
SoftwareManagedBean.java
#ManagedBean(name = "swmb")
#ViewScoped
public class SoftwareManagedBean extends AssetManagedBean implements
Serializable {
private String bezeichnung;
private Software neueSoftware;
// +some more private fields, every single one with its get-/set-method
#Override
public String getBezeichnung() {
return super.getBezeichnung();
}
#Override
public void setBezeichnung(final String bezeichnung) {
super.setBezeichnung(bezeichnung);
}
//instantiante the field "neueSoftware"
public void createEmptySoftware(){
if(neueSoftware != null)
return;
this.neueSoftware = new Software();
}
//Persist Software with values from inputFields
public void addSoftware() {
createEmptySoftware();
neueSoftware.setBezeichnung(getBezeichnung());
softwareService.addSoftware(neueSoftware);
//...
neueSoftware = null;
}
viewSoftware.xhtml
<h:body>
<p:dialog header="Neue Software anlegen" widgetVar="SwNeuDialog" width="60%"
closeOnEscape="true" draggable="false" resizable="false" position="center">
<h:form id="SwDlgForm">
<h:panelGrid columns="3" border="0" >
<p:outputLabel for="swBezeichnung" value="Bezeichnung: " />
<p:inputText id="swBezeichnung" value="#{swmb.bezeichnung}"
label="Bezeichnung" required="true" />
<f:verbatim/>
<p:outputLabel for="swKategorie" value="Kategorie: " />
<p:selectOneMenu id="swKategorie" value="#{swmb.kategorie}" label="Kategorie" required="true" >
<f:selectItem itemLabel="Kategorie wählen" value="#{null}" noSelectionOption="true"/>
<f:selectItems value="#{swmb.kategorieListe}" var="kat" itemLabel="#{kat.bezeichnung}" itemValue="#{kat}"/>
</p:selectOneMenu>
<p:commandButton value="neue Kategorie hinzufügen" />
<!-- + some more input fields -->
<p:commandButton value="Speichern" action="#{swmb.addSoftware()}" onclick="PF('SwNeuDialog').hide()" resetValues="true" process="#this"/>
<p:commandButton value="Abbrechen" onclick="PF('SwNeuDialog').hide()" resetValues="true" process="#this"/>
</h:panelGrid>
</h:form>
</p:dialog>
<!-- dataTable -->
</h:body>
AssetManagedBean.java
#ManagedBean
public abstract class AssetManagedBean {
//name of the hard-/software
private String bezeichnung;
//+ some more fields with get-/set methods
public String getBezeichnung() {
return bezeichnung;
}
public void setBezeichnung(String bezeichnung) {
this.bezeichnung = bezeichnung;
}
I hope that code is sufficient to see the problem, since the rest of the code follows the same structure. I think, the problem could lie within the xhtml file, but I don't see where or why. I've got the SpringBeanFacesELResolver (or however it is called), I've already looked through the code and compared it to another xhtml page and its Managed Bean, but there are no differences anymore. (though one is working, one not)
My debugger showed, how the working class/page (viewAdministration.xhtml) called the get-/set methods of the managed bean:
opening dialog window: get...(), set...()
clicking the commandButton to submit/persist: get() (old Value), set() (new Value), get() (new Value)
Another get() (called by the add... method)
(+ another get() for the dataTable on the main page)
on viewSoftware.xhtml, it looks like this:
opening dialog window: get()
clicking the commandButton to submit/persist:
another get() called by the addSoftware method
As you can see, when I try to submit, there is no set or get.
So, to summarize:
no setter called by trying to submit
the code on viewSoftware.xhtml and SoftwareManagedBean is similar to another, functioning ManagedBean + xhtml page (I've compared it again and again)
annotations in Managed Beans are the same (#ManagedBean, #ViewScoped)
the inputFields are inside a form (
I'm totally clueless, but I think it is some small mistake from my side that I can't just see.
I've searched through the web and especially stackoverflow, but all the problems and answers I've found couldn't help me finding what's wrong
Even without inheriting from a superclass it won't work (tried that out too)
I hope, you can help me. If this post is lacking some information, I'm sorry about that, I tried my best to not let this post grow too big and still get as much relevant information in it as possible.
So, I have found my mistake (or at least, I think I have). Only took me 2 weeks, but anyway...
I tried to test it out more specifically, wrote test classes and an xhtml page. Nothing worked (from simple Input over Dates to own classes).
The solution to this problem was to disable ajax on my commandButton (ajax="false"). When I tried to understand more of it, I realized that the commandButton opening the dialog window was nested in a facet inside a dataTable, and thus it had problems to properly set the values of the input fields.
So, thank you for your help. Maybe/hopefully this can or will help some other people later as well.
From the first glance at the code, without reading it whole, try putting process="SwDlgForm" on your command buttons, instead of process="#this". If that doesn't solve the problem, I'll read more carefully and try to help.

Access iteration variable in passthrough attribute?

I'm wondering why I get a NullPointerException on the following:
<h:dataTable value="#{testBean.entities}" var="d">
<h:column p:data-order="#{d.modifiedOn}">
<f:facet name="header">Date</f:facet>
<h:outputText value="#{d.modifiedOn}">
<f:convertDateTime pattern="#{msg.datePattern}" />
</h:outputText>
</h:column>
</h:dataTable>
Where the p namespace is xmlns:p="http://xmlns.jcp.org/jsf/passthrough", modifiedOn is a (non-null) Date field.
The exception looks like this:
Caused by: java.lang.NullPointerException
at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.getAttributeValue(HtmlResponseWriter.java:1211)
at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.flushAttributes(HtmlResponseWriter.java:1171)
at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.closeStartIfNecessary(HtmlResponseWriter.java:1113)
at com.sun.faces.renderkit.html_basic.HtmlResponseWriter.writeText(HtmlResponseWriter.java:936)
at com.sun.faces.facelets.el.ELText$ELTextVariable.writeText(ELText.java:240)
at com.sun.faces.facelets.compiler.TextInstruction.write(TextInstruction.java:85)
at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:302)
at com.sun.faces.renderkit.html_basic.TableRenderer.renderHeader(TableRenderer.java:339)
However, use of #{d.modifiedOn} is fine in any non-passthrough attributes like headerClass. As is any value not referencing the iteration variable in a passthrough attribute.
My question is: is this intended?
This is using Wildfly-8.0.0.Final's JSF implementation, version 2.2.5-jbossorg-3.
In case anyone's wondering: I'm trying to support datatables orthogonal data attributes to enhance my tables.
Edited to add: I've also tried, but got the same Exception, with adding the following to the <h:column>:
<f:passThroughAttribute name="data-order" value="#{d.modifiedOn}" />
This is apparently caused by JSF trying to render this attribute on the header where rowIndex is -1 and iteration data is not yet present. So there's an hack solution to my specific problem:
<h:column p:data-order="#{empty d or empty d.modifiedOn ? '' : d.modifiedOn.time}">
...
</h:column>
Which still renders an empty/useless data-order attribute into my thead.
Further testing:
More testing has confirmed my suspicion that this only occurs with a <f:facet name="header"> on any column (doesn't have to be the one with the attribute). Leaving those out defeats my goal of using the table as a base for datatables since that requires a well-formed table with a <thead>.
Is this intended? Definitelly it's not. Furthermore, here is the definition of a passthrough attribute according to the JSF 2.2 specification:
Pass Through Attributes
For any given JSF component tag in a view, the set of available attributes that component supports is determined by a
combination of the UIComponentand Renderer for that tag. In some cases the value of the attribute is interpreted by
the UIComponentor Renderer(for example, the columns attribute of h:panelGrid) and in others the value is
passed straight through to the user agent (for example, the lang attribute of h:inputText).
In both cases, the
UIComponent/Renderer has a priori knowledge of the set of allowable attributes. Pass Through Attributes allows
the view author to list arbitrary name value pairs that are passed straight through to the user agent without interpretation
by the UIComponent/Renderer. This behavior is normatively specified in the “Rendering Pass Through Attributes”
section of the overview of the standard HTML_BASIC render kit.
So the only functionality of that kind of attributes is to notify the renderer that it must process the value for the attribute, but that it's not tied to any of the UIComponent features, so must end up at the final output.
I have performed a test with Tomcat 7 + Mojarra 2.2.6 and it perfectly works for me. HTML elements get rendered in the DOM tree with their data-order attribute, with the given date. That's the test case I've used:
<html xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://xmlns.jcp.org/jsf/passthrough">
<h:head />
<h:body>
<h:dataTable value="#{bean.entities}" var="entity">
<h:column p:data-order="#{entity.modifiedOn}">
#{entity.name}
</h:column>
</h:dataTable>
<h:messages />
</h:body>
</html>
#ManagedBean
#ViewScoped
public class Bean {
public class Entity {
private String name;
private Date modifiedOn;
public Entity(String name, Date modifiedOn) {
this.name = name;
this.modifiedOn = modifiedOn;
}
public Date getModifiedOn() {
return modifiedOn;
}
public String getName() {
return name;
}
}
/**
* Create a List of entities with dates differing from now to now + 2 days
*/
public List<Entity> entities = Arrays.asList(
new Entity("name1", new Date()), new Entity("name2", new Date(
new Date().getTime() + (1000 * 60 * 60 * 24))), new Entity(
"name0", new Date(new Date().getTime()
+ (1000 * 60 * 60 * 48))));
public List<Entity> getEntities() {
return entities;
}
}
This means it's a bug in your JSF implementation (implementation which I didn't know about BTW). Your best is opening a bug track unless the authors have already fixed it in a later version.
Edit
The rendering fails with the given error when there's an f:facet for header or footer involved for the datatable. Apparently, Mojarra tries to evaluate the passthrough value for the facet before building the iterator, that causes it to fail as the variable is not yet available. Opened an issue.
See also:
JSF 2.2 specification

Sorting in primefaces datatable

I am using primefaces datatable to show my data in UI. As we all know., we can do sorting and filtering in the data table itself. But it starts to search the data when I type a single character in the datatable sorting field, I dont want it. I need to search the data only when the user types atleast 3 characters in the field. Is it possible to do that..? If so., in what way? please provide your comments on that.
Thanks in advance.
I did a small investigation of Primefaces' data table and here are my findings.
Actually, recompilation is not necessary, source javascript substitution as well.
You need to register a new handler for filter event instead of the the one provided by Primefaces.
In this case a data table will be used like this:
<h:outputScript name="js/customprimefacestable.js" target="body"/>
<p:dataTable var="data" value="#{filterBean.data}" filteredValue="#{filterBean.filteredData}" widgetVar="tableWidget">
<p:column filterBy="#{data.name}" headerText="Name" filterMatchMode="contains">
<h:outputText value="#{data.name}" />
</p:column>
<p:column filterBy="#{data.value}" headerText="Value" filterMatchMode="contains">
<h:outputText value="#{data.value}" />
</p:column>
...
</p:dataTable>
And the javascript will be like this:
$(document).ready(function() {
tableWidget.thead.find('> tr > th.ui-filter-column > .ui-column-filter').each(function() {
var filter = $(this);
if(filter.is('input:text')) {
if(tableWidget.cfg.filterEvent!="enter"){
//unbind current handler
filter.unbind(tableWidget.cfg.filterEvent);
//bind new handler that accounts for conditional filtering
filter.bind(tableWidget.cfg.filterEvent, function(c) {
if(filter.val().length > 3) {
//Primefaces 3.5 implementation
if(tableWidget.filterTimeout){
clearTimeout(tableWidget.filterTimeout);
}
tableWidget.filterTimeout=setTimeout(function(){
tableWidget.filter();
tableWidget.filterTimeout=null},
tableWidget.cfg.filterDelay);
}
});
}
}
});
});
Things to note:
target="body": the javascript must not be executed in the <head>, because Primefaces initializes its widget variables in $(document).ready(), so it is not guaranteed that your function will execute after the Primefaces initialization has taken place;
as the filtering starts with at least 4 characters typed in column's search box (done), you should restore unfiltered view when user deletes text to below 4 characters by yourself (not done);
the solution above is aimed at Primefaces 3.5 <p:dataTable>. Primefaces implementation varies from version to version, so be sure to check out the implementation of the version you are using, or upgrade to version 3.5;
implementation of filtering events with input fields rendered as dropdown boxes is not covered;
the table will listen to the default (keyup) event.

PF's graphicImage doesn't render

I'am using JSF/PF anf I can't make a graphicImage work. Reviewing the tons of topics published on forums, this PF's graphicImage seems to be so tricky. I am obviously doing somethig wrong, but, as long as I am replicating code that worked for others (see post), it must be something in the environment of the component. I hope to find a solution here, i'm stuck for weeks. Thanks
Here is my original question in PF forum:
I encounter a problem rendering the image. I have followed the code explained and I correctly retrieve the id for image to display in a separate method:
public StreamedContent getStreamedImage() {
StreamedContent streamedImage = null;
UIViewRoot uiRoot = FacesContext.getCurrentInstance().getViewRoot();
System.out.println(uiRoot.getClientId());
UIComponent component = FacesContext.getCurrentInstance().getViewRoot().findComponent("itemDataForm:imagesTbl:itemImgComp");
Map attributes = component.getAttributes();
Integer image_id = (Integer)attributes.get("item_img_id");
if(image_id != null && editionItem != null && editionItem.getImages() != null){
for(ItemImageView img : editionItem.getImages()){
if(image_id.intValue() == img.getId()){
streamedImage = new DefaultStreamedContent(new ByteArrayInputStream(img.getImage()), "image/jpeg");
}
}
}else{
streamedImage = new DefaultStreamedContent(new ByteArrayInputStream(editionItem.getImages().get(0).getImage()), "image/jpeg");
}
.......
I could't manage to retrieve the (always null) so I tried with attribute and it works. So, the DefaultStreamContent is loaded, by the image doesn't render at all. My code for xhtml:
<p:dataTable id="imagesTbl" var="itemImg" value="#{itemEditionBean.editionItem.images}">
<p:column>
<h:panelGrid columns="1">
<h:outputText value="#{itemImg.id}"/>
<p:graphicImage id="itemImgComp" value="#{itemEditionBean.streamedImage}">
<f:attribute name="item_img_id" value="#{itemImg.id}"/>
</p:graphicImage>
</h:panelGrid>
</p:column>
</p:dataTable>
Exactly the same that the code working in this topic above. PS: I have mt dataTable enclosed within a tab. Maybe a dependency on the enclosing component, or form, or what?
There is a huge amount of code from other related topics that can be viewed in the link below:
http://forum.primefaces.org/viewtopic.php?f=3&t=4163&p=39751
Based on another page I found on building dynamic images, <f:param .../> should be used to supply a parameter to the getStreamedImage() method rather than <f:attribute .../>. Are you using a ConversationScoped backing bean? I was having the same problem displaying dynamic images, but found that there is a problem using them with ConversationScoped beans. I switched my backing bean to Session scope and now it works fine.

Resources