I have the next code to load a set of images whose streams are in a datamodel called names. My problem is when I declare the var inside the p:datatable tag seems like has nothing. Any idea?
thx!
<p:dataTable value="#{controlador.names}" var="nombre" rendered="true">
<p:column rendered="true">
<h:outputText value="#{nombre.stream}"/>
<p:graphicImage value="#{nombre.stream}"/>
</p:column>
</p:dataTable>
The p:graphicImage uses another request so you need to pass an identifier to the managedBean like this.
<p:dataTable value="#{productManaged.products}" var="productIterated">
<p:column>
<f:facet name="header">
<h:outputText value="#{product.pic}"/>
</f:facet>
<p:graphicImage value="#{productManaged.dynamicProductImage}">
<f:param name="product_id" value="#{productIterated.id}"/>
</p:graphicImage>
</p:column>
</p:dataTable>
Another thing that you should take care is to return something in the StreamedContent or is gonna fail. Do something like this:
public StreamedContent getDynamicProductImage() {
String id = FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get("product_id");
if(id!=null && this.products!=null && !this.products.isEmpty()){
Integer productId = Integer.parseInt(id);
for(Product productTemp:this.products){
if(productTemp.getId().equals(productId)){
return new DefaultStreamedContent(
new ByteArrayInputStream(productTemp.getImage()),
productTemp.getMimeType());
}
}
}
return new DefaultStreamedContent(
new ByteArrayInputStream(this.products.get(0).getImage()),
this.products.get(0).getMimeType()); //if you return null here then it won't work!!! You have to return something.
}
or you can read this thread http://primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=4163
After wasting hours of going the the process of implementing the many solutions I found for this issue (i.e. including a param or attribute), The only solution I managed to find that actually works can be found here: Serving Dynamic Content with PrettyFaces
Remove the <h:outputText>. You can read a stream only once. It cannot be re-read another time.
As to the p:graphicImage part, you need to feed it with a value of DefaultStreamedContent. Also see this blog entry.
Related
i have a problem with this primefaces component in my view xhtml. I builded a searchbar that filters elements in a list based on the value of this inputText component with an ajax call on event. Everything works like it should, till i press enter in inputText, then my filter method does unexpected things. Thats why i tried to avoid pressing enter. But like in the snipped below, the listener isn't called even if key != 13.
Does anybody have a idea?
Thanks for your help!
<p:inputText value="#{ListView.filter}" style="width:150px" placeholder="Stichwort">
<p:ajax event="keyup" onevent="if (event.keyCode == 13) { return false; }" listener="#{ListView.filterAvailable}" update="#form"/>
</p:inputText>
You can just try this directly on the inputText tag. I usually do this with Internet Explorer.
<p:inputText id="testInput" onkeydown="if(event.keyCode==13) return false;" [....]
You can simply add a condition in front of it like :
<p:inputText id="testInput" onkeydown="#{mySessionInfoBck.ieBrowser ? 'if(event.keyCode==13) return false;' : ''}" [....]
the Datatable is displaying only the last item added, it seems that every time i press the commandButton the method rewrites the list, what can I do to avoid that?
JSF
<p:commandButton action="#{productoBean.setPedidoActual()}" value="Agregar" update="dt"/>
</p:panelGrid>
<p:dataTable value="#{productoBean.pedidoActual}" var="pedi">
<p:column headerText="Nombre">
<h:outputText value="#{pedi.descripcion}"/>
</p:column>
</p:dataTable>
Bean
public void setPedidoActual() {
Producto pro = productoFacade.find(idProducto);
listPedidoActual.add(pro);
}
public List<Producto> getPedidoActual() {
return listPedidoActual;
}
Your setPedidoActual() method seems like to receive only one item based on the facade service find(idProducto), is that correct? Have you checked what the remote service returns? Probably there is in fact just one record.
Beside that, try to rename your setter/getter from
getPedidoActual() / setPedidoActual()
into
getListPedidoActual() setListPedidoActual()
Now your method names are consistent with your attribute.
EDIT: What happened to the panelGrid tag? Have you purposely omitted or where does it start?
I am using primefaces 4.
I am using an editable table and when I edit a cell, a listener method is called passing a CellEditEvent
Like this
public void onCellEdit(CellEditEvent event) {
/*
* The rowIndex here can be changed according to the sorting/filtering.
* FilteredData starts as null, but primefaces initializes it, so you
* don't have to check for NPE here
*/
int alteredRow = event.getRowIndex();
UIColumn o = event.getColumn();
System.out.println(this.filteredData.get(event.getRowIndex()).get(columns.get(0)));
}
So far, so good.
The event has a getRowIndex()
But it does not have a getColumnIndex().
Instead, it has a getColumn() method that returns a UIColumn object.
The problem is, while debugging, I could not find a way to get any column information (name, id, etc)
I can hack the column to have some unique ID like this
<p:ajax event="cellEdit" listener="#{myMB.onCellEdit}"/>
<c:forEach items="#{myMB.columns}" var="column" varStatus="loop">
<p:column id="col#{loop.index}" headerText="#{column}" sortBy="#{column}" filterBy="#{column}" filterMatchMode="contains"/>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{dataRow[column]}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{dataRow[column]}" />
</f:facet>
</p:cellEditor>
</p:column>
</c:forEach>
But still I can't find a way to retrieve the column id from the CellEditEvent
So, assuming that a cell is something that has a row and a column, I have to ask
How do I retrieve the column of an edited cell in a CellEditEvent?
ps. I feel I am missing something, because no one would create a cell event without providing the row and the column, right?
update - it seems I can get the ID like
org.primefaces.component.column.Column o = (org.primefaces.component.column.Column)event.getColumn();
still, this seems like a hack for me. I am still interested in more elegant solutions for this ;-)
You can get the column by referring back to the column header that you passed.
In bean you could do this:
public void onCellEdit(CellEditEvent event) {
int alteredRow = event.getRowIndex();
String column_name;
column_name=event.getColumn().getHeaderText();
// now you can use this to identify the column we are working on.
}
Using getColumnId() or getColumnKey() returns the column Id but with primefaces code added to it - making it difficult to work with.
If you use p:columns rather than p:column - which is also more readable - event.getColumn() returns a DynamicColumn that implements UIColumn. Then you can use:
((DynamicColumn)event.getColumn()).getIndex()
to determine the column index. There is also a column.isDynamic() to check validity.
Using the header would need further code and might be more inefficient.
I found only one way to do this. On the xhtml, add an id to the column:
<p:column id="myColumn">
...
</p:column>
In the backing bean,column.getColumnKey() will return a generated id that contains the id you set in the xhtml (something like j_idt30:j_idt32:0:contratoReal). Thus, you can do this:
public void onCellEdit(CellEditEvent event) {
if (event.getColumn().getColumnKey().endsWith("myColumn")
}
I've got a problem considering JSF and AJAX.
I am trying to update some customer details after a visitor inserts the customer id.
Firstly, a excerpt from the xhmtl code:
<h:form>
<h:panelGrid columns="2">
<h:panelGrid columns ="2" border="1" id="customer_grid">
<h:outputLabel value="#{mbean_msg.reservation_lblCustomerNo}" for = "customer_id"/>
<h:inputText id = "customer_id" value="#{reservationHandler.customer.customer_id}">
<f:ajax listener="{reservationHandler.autocompleteCustomerDetails}"
render="customer_grid" />
</h:inputText>
<h:outputLabel value="#{mbean_msg.reservation_lblLastname}" for="lastname"/>
<h:inputText id="lastname" value="#{reservationHandler.customer.lastname}" required ="true"
requiredMessage="#{error_msg.errmsgLastname}" validator="#{reservationHandler.validateCustomer}"/>
<h:outputLabel value="#{mbean_msg.reservation_lblFirstname}" for="firstname"/>
<h:inputText id="firstname" value="#{reservationHandler.customer.firstname}" required ="true"
requiredMessage="#{error_msg.errmsgFirstname}" validator="#{reservationHandler.validateCustomer}"/>
The listener method is implemented within my java file (ReservationHandler.java) like that:
public void autocompleteCustomerDetails(){
System.out.println("Auto Complete"); // for testing
}
Basically I am trying to call the method autocompleteCustomerDetails with the Listener. Unfortunately this method is never called. Anyways, the render seems to work just fine, since the other inputTexts update themselves (visibly).
Does anybody have an idea, why the listener isn't called?
There are two problems in the code shown so far:
First,
<f:ajax listener="{reservationHandler.autocompleteCustomerDetails}" />
this isn't a valid EL expression. EL expessions have the form of #{}, not {}. Fix it accordingly:
<f:ajax listener="#{reservationHandler.autocompleteCustomerDetails}" />
Second,
public void autocompleteCustomerDetails() {
this isn't a valid default signature of a method expression for <f:ajax listener>. The tag documentation clearly tells the following:
signature must match public void processAjaxBehavior(javax.faces.event.AjaxBehaviorEvent event) throws javax.faces.event.AbortProcessingException.
So, you forgot the argument. Add it accordingly. The throws declaration isn't mandatory for unchecked exceptions, so we can just leave it out.
public void autocompleteCustomerDetails(AjaxBehaviorEvent event) {
Or, if you actually intend to get rid of the argument, then you should put parentheses in the EL method expression:
<f:ajax listener="#{reservationHandler.autocompleteCustomerDetails()}" />
Note that this works only if your container supports EL 2.2.
Try this:
<f:ajax listener="{reservationHandler.autocompleteCustomerDetails()}"
render="customer_grid" />
or change the method to:
getAutoCompleteCustomerDetails
just for testing...
Anyhow, you´re not allowed to use any jsf's components library? Like primefaces ?
It gets the job done in such a easy way...
Anyhow, with primefaces I would do that like this:
<p:ajax event="blur" listener="#{prospectoRadarController.atualizarRadar(data)}" update=":mainForm:painelRadar" />
Another guess would be, add the execute="#this" to the ajax flag...
Sorry, those are all wild guesses, but I really want to help.
PLease feedback!
I'm using Primefaces 3.4 and trying to export a data-table with in-cell editing. It doesn't seem to work.
I have done the following:
Modified org.primefaces.component.export.Exporter line 143 and added this:
else if (component instanceof CellEditor) { // Handle in-cell editable datatables
return exportValue(context, ((CellEditor) component).getFacet("output"));
}
This is causing an extra row on top as well as an extra column to the right of the actual cells with data. With Excel files it's OK since they are not "visible" but PDF looks bad.
Is there a way to make PF 3.4 support this without changing the source code?
If the answer to the above is negative, can I make the PDF get generated without the additional row/column?
Is there a way to make PF 3.4 support this without changing the source code?
No. You've to provide your custom Exporter implementations/overrides. I've already reported this as issue 4013 several months ago. It not only mentions CellEditor, but also HtmlGraphicImage (we are using images to show boolean states, whose alt we'd like to show in PDF/XML/XLS/CSV reports).
All you can do is to vote for it so that it'll hopefully get more attention, or by re-asking it on PF forum.
If the answer to the above is negative, can I make the PDF get generated without the additional row/column?
You can hide a column from export by setting the exportable="false" attribute.
<p:column exportable="false">
Is there a way to make PF 3.4 support this without changing the source code?
Yes. There is a workaround
Make two copies of your column.
First one is for users and second one is for dataExporter.
By setting exportable="false" in first column, hide it from dataExporter.
By setting style="display: none" in second column, hide it from users.
By the way dataExporter does not support headerText so if you need your headerText exported you have to use old style <f:facet name="header">.
<p:column headerText="CLOSE DATE" exportable="false">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{sale.closedate}"/>
</f:facet>
<f:facet name="input">
<h:inputText value="#{sale.closedate}"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column style="display: none">
<f:facet name="header">
CLOSE DATE
</f:facet>
<h:outputText value="#{sale.closedate}"/>
</p:column>
But this workaround is plain ugly and makes your dataTable twice in size and hard to render.
As BalusC mentioned we need to rise awareness about this issue by voting or posting in their forum.
The only solution that I've found so far is to make your own class that extends Exporter and to override method protected String exportValue(FacesContext context, UIComponent component). You should only add
else if (component instanceof CellEditor) {
return exportValue(context, ((CellEditor) component).getFacet("output"));
}
the answer is... create a data table with cell editor....
and after create an other table with no cell editor but the same fields into a
the exporter should be reference to the second table, and it is! :D
greetings!