I'm working on a jsf application. I have a dataTable, I use one column to render the description of a Pojo.
The problem is : This description it too long and the dataTable is not perfectly lisible.
Is there a way to limit the number of caracteres to render on the description column of this dataTable like : Description desc desc...
If you are using JSF 2, you can use the function of:abbreviate from the OmniFaces project.
Put the JAR file in your WEB-INF/lib, configure the namespace accordingly in your XHTML file like this:
<html ... xmlns:of="http://omnifaces.org/functions">
and then you can use it on any String property, like this:
<h:column>
<h:outputText value="#{of:abbreviate(someBean.myproperty, 20)}" />
</h:column>
See the demo here.
If you are getting the string from a database, try to use the Substring SQL function to truncate the data directly when you get it from the DB.
If not, you can try the solution below.
Let us say that the POJO class (call it MyPOJO) you are using contains a String attribute called description. Now the DataTable will be linked to a List or Map etc... of that object, lets make it an "ArrayList<MyPOJO> theList" for now.
What you can do is have another attribute in the same class MyPOJO. Declare that as String descriptionTruncated and in the getter method of that String write the following:
public String getDescriptionTruncated() {
if (this.description == null) {
return description;
} else if (this.description.length() <= 20 ) {
return description;
} else {
return description.substring(0,19);
}
}
We assume here that the desired length is 20.
And then in the Datatable reference the newly created String like this :
<h:datatable ... var="pojoObj">
<h:column>
<h:outputText value="#{pojoObj.descriptionTruncated}" />
</h:column>
Hope that helps.
Related
I have a selectOneMenu that loads a list of BD, debugging can ve that all steps are correct except the time it shows the value in selectOneMenu. On page appears the object name "JanelaPortabilidade # 7437" and not like the String.
My codes:
public List<SelectItem> listarHoraJanela(DateSelectEvent event) {
dataF = event.getDate();
Calendar dataAux = new GregorianCalendar();
dataAux.setTime(dataF);
//Corrigir
if (listaHoraJanela == null) {
listaHoraJanela = new ArrayList<JanelaEAPortabilidade>();
listaHoraJanela = consultaJPortabilidade.listarHoraJanela(dataAux);
listSelectHoraJ.add(new SelectItem("", ""));
for (JanelaEAPortabilidade horaJ : listaHoraJanela) {
String dataFormat = String.format("%02d",horaJ.horIniJanela.get(Calendar.HOUR_OF_DAY));
System.out.println(dataFormat);//So here is ok, print in console correct string
listSelectHoraJ.add(new SelectItem(horaJ.getIdtJanela(),dataFormat));
}
}
xhtml:
<h:outputText value="Hora da Janela:" for="horaJanela" />
<h:selectOneMenu value="#{bean.codHoraJanela}" id="horaJanela"
rendered="#{bean.type == 'Fixo'}" >
<f:selectItems value="#{bean.listaHoraJanela}" />
What can it be? I must be missing something.
Thank you!
What you need to do is to use the itemLabel and itemValue attributes for f:selectItems. Here is an example from the PrimeFaces website (http://www.primefaces.org/showcase-labs/ui/selectOneMenu.jsf from the pojo section of the code):
<f:selectItems value="#{autoCompleteBean.players}" var="player" itemLabel="#{player.name}" itemValue="#{player}"/>
The itemLabel is what will be displayed in the drop down list and itemValue is what will be returned (in #{bean.codHoraJanela} in your example).
I'm surprised the code even works. If I didn't miss something the code should throw a NullPointerException. In the JSF you posted a DateSelectEvent isn't created, instead the method is called without any arguments. The DateSelectEvent in the Java method should therefor be NULL.
The output you see is the result of an object's toString() method. Probably the object represented there is coming from the codHoraJanela method in the managed bean. Fix the listarHoraJanela method to return a list of objects.
I have a datatable where I want to change the color of a cell based on some analysis that is run on the contents. The table is linked to an array of Comment objects, which I have given a String cssClass that gets updated once the analysis is run. This is what I have tried plugging into the rowClasses property of the datatable. It's not working and I think the issue may be that I cannot access the variable created for each row of the datatable, from inside the datatable declaration.
Datatable code:
<h:dataTable value="#{post.comments}" var="comment" class="hs-table" rowClasses="#{comment.cssClass}" >
<h:column>
#{comment.name}
</h:column>
<h:column>
#{comment.email}
</h:column>
<h:column>
#{comment.msg}
</h:column>
</h:dataTable>
The Comment class:
public class Comment {
private String msg;
private String email;
private String name;
private Date date;
private String cssClass;
public Comment(){
cssClass = "normColumn";
}
epublic String getCssClass() {
return cssClass;
}
public void setCssClass(String cssClass) {
this.cssClass = cssClass;
}
}
Where the cssClass is updated in the managed bean:
if(tone>0)
c.setCssClass("commentPos");
else if(tone<0)
c.setCssClass("commentNeg");
The class never gets assigned. Am I doing something wrong, or is this simply not possible?
In the standard JSF <h:dataTable> component, the rowClasses attribute is unfortunately not evaluated on a per-row basis. It's evaluated on a per-table basis. Component libraries like Tomahawk and PrimeFaces however support the kind of attribute which you're looking for on their <t:dataTable> and <p:dataTable>.
With the standard JSF <h:dataTable> component you need to supply a comma-separated string of all row classes. This can look something like this:
public String getRowClasses() {
StringBuilder rowClasses = new StringBuilder();
for (Comment comment : comments) {
if (rowClasses.length() > 0) rowClasses.append(",");
rowClasses.append(comment.getCssClass());
}
return rowClasses.toString();
}
which is then to be referenced as
<h:dataTable ... rowClasses="#{post.rowClasses}">
See also:
<h:dataTable> tag documentation - lists all attributes and the accepted values
I mean this. I have a JSF page with a PrimeFaces Datatable, and I want to get a rowstyleClass name from bean. But bean method should check a record from table to return a String value of styleClass.
can I do something like this
#ManagedBean(name="styleController")
#SessionScoped
public class StyleController {
public StyleController() {
}
public String getContractStyle(ContrMain contrMain){ //ContrMain - entity class
if(contrMain.getCloseDate()!=null && contrMain.getClosedBy()!=null){
return "closed";
}else{
return "acting";
}
}
}
and in JSF page something like this
<p:dataTable value="#{contrMainController.items}"
var="item"
...
rowStyleClass="ui-datatable-#{styleController.contractStyle(item)}">
I know that it doesn't work. And is there some way to use an "item" variable?
I have found decision.
the answer is simple.
rowStyleClass="ui-datatable-#{styleController.getContractStyle(item)}"
instead of
rowStyleClass="ui-datatable-#{styleController.contractStyle(item)}"
works fine
I'm trying to create a paginated, sortable datatable using MyFaces. The sorting works fine; I can click on a column header and it will sort the data based on the column. Also the pagination works fine for the most part. The datatable will split itself appropriately with some number of items per page. In addition, I want the user to be able to change the number of items displayed per page. Again, this seems to be working until I want all of the items displayed on one page.
According to this reference (also here), if you set the "rows" attribute of t:datatable to "0", it will display the remaining rows in the table. However, when I try this, I get an exception that includes this message:
javax.faces.FacesException - You need to set a value to the 'rows' attribute of component 'myComponent'
I'm trying to set the number of items per page using an attribute in a backing bean. My t:datatable looks like this:
<t:dataTable id="myComponent" var="cur"
value="#{backingBean.list}" sortAscending="#{backingBean.ascending}"
sortColumn="#{backingBean.sortColumn}" sortable="true"
styleClass="myClass" rowClasses="oddRow,evenRow"
rows="#{backingBean.itemsPerPage}" preserveDataModel="false">
<!-- data here -->
</t:datatable>
Later, I have a t:dataScroller to control the pagination:
<t:dataScroller id="pageNavigation" for="myComponent"
paginatorActiveColumnStyle="font-weight:bold;"
renderFacetsIfSinglePage="false"
binding="#{backingBean.scroller}"
paginator="true" >
<!-- facets here -->
</t:dataScroller>
Then, I have a h:selectOneMenu to select the number of items per page
<h:selectOneMenu id="myScroller"
value="#{backingBean.itemsPerPage}"
required="true" onchange="this.form.submit();"
valueChangeListener="#{backingBean.updateItemsPerPage}">
<f:selectItems value="#{backingBean.itemsPerPageArray}" />
</h:selectOneMenu>
My backing bean looks something like this:
public class BackingBean {
private boolean ascending;
private Long itemsPerPage;
private String sortColumn;
private ArrayList<SelectItem> itemsPerPageArray;
private ArrayList<SomeObject> list; // data for table
private HtmlDataScroller scroller;
// constructors, getters, setters, and other stuff here
public void updateItemsPerPage(ValueChangeEvent valueChangeEvent) {
itemsPerPage = (Long) valueChangeEvent.getNewValue();
resetScrollerIndex();
}
private void resetScrollerIndex() {
if (scroller!=null && scroller.isPaginator())
scroller.getUIData().setFirst(0);
}
// called in constructor
private void constructItemsPerPageArray() {
itemsPerPageArray = new ArrayList<SelectItem>();
itemsPerPageArray.add(new SelectItem(new Long(10), "10"));
itemsPerPageArray.add(new SelectItem(new Long(50), "50"));
itemsPerPageArray.add(new SelectItem(new Long(100), "100"));
itemsPerPageArray.add(new SelectItem(new Long(0), "All"));
}
}
To sum up, when I select the "All" item from the h:selectOneMenu, I get the exception mentioned above. Hopefully, I've included an appropriate level of detail. Thanks!
Alright, I think I found the answer...
If I remove the first line from the updateItemsPerPage method, the problem is fixed. The method now looks like:
public void updateItemsPerPage(ValueChangeEvent valueChangeEvent) {
resetScrollerIndex();
}
It thought I had tried that...
can some one help me with the following JSF dataTable? here I am getting data from database table and I used dataTable binding, but I don't know why it displays the rows 3 times in the screen, but if I remove the binding then it displays only one time.
<h:dataTable binding="#{threadController.dataTable}" var="category" value="#{threadController.queryCategories}" border="1" cellpadding="2" cellspacing="0">
<h:column>
<img src="../../images/directory.jpg" alt="Forum Icon" />
</h:column>
<h:column>
<h:form>
<h:commandLink value="#{category.cname}" action="#{threadController.categoryDateItem}" />
</h:form>
</h:column>
// defined globally
private HtmlDataTable dataTable;
private HtmlInputHidden dataItemId = new HtmlInputHidden();
public String categoryDateItem() {
category = (Category) dataTable.getRowData();
System.out.println("category action by select: "+category.getCname());
dataItemId.setValue(category.getId());
return "editItem"; // Navigation case.
}
#SuppressWarnings("unchecked")
public ArrayList<Category> getQueryCategories(){
return (ArrayList<Category>)HibernateUtil.getSession().createCriteria(Category.class).list();
}
output:
myText myText myText
The binding expression to bind this component to the bean value="#{threadController.queryCategories}".So value attribute is sufficient to retrieve data using dataTable tag.
Binding = component backing bean
Value= data model backing bean
So, you have the Value and Binding set correctly (at least, as far as I can see). Your problem may result from the fact that you're not caching the list you're getting back from the database in getQueryCategories().
You really can't have any idea how often getQueryCategories() will be called in the process of rendering that dataTable, so it's a good idea to do something like this:
// Somewhere near the top of the handler class.. create a cache variable:
private ArrayList<Category> qCategories = null;
// now for getQueryCategories
public ArrayList<Category> getQueryCategories(){
if ( qCategories == null ) { // qCategories should be a member of the handler
qCategories = (ArrayList<Category>)HibernateUtil.getSession().createCriteria(Category.class).list();
}
return qCategories
}
This kind of cache-ing is very helpful in JSF apps with handlers that are session of even request scoped, as again you can't really know how often JSF will evaluate your "value" expression in the dataTable.