Cannot get sortBy work in RichFaces 4 - jsf

I am following this example: http://mkblog.exadel.com/2008/11/richfaces-built-in-sorting/
it its said that arrows should appear beside the header and the user can click it to sort.
But I cannot get the arrow appear. You help appreciated.
The code I use:
newwonder.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:rich="http://richfaces.org/rich">
<h:head>
<title>Requirement Workflow</title>
</h:head>
<h:body>
<rich:dataTable value="#{newWondersBean.sevenNewWonders}" var="wonder">
<rich:column sortBy="#{wonder.name}">
<f:facet name="header">Name</f:facet>
<h:outputText value="#{wonder.name}" />
</rich:column>
<rich:column sortBy="#{wonder.location}">
<f:facet name="header">Location</f:facet>
<h:outputText value="#{wonder.location}" />
</rich:column>
<rich:column>
<f:facet name="header">Image</f:facet>
<h:graphicImage url="#{wonder.imageUrl}" />
</rich:column>
</rich:dataTable>
</h:body>
</html>
NewWondersBean.java
package wonder;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class NewWondersBean {
private ArrayList <Wonder> sevenNewWonders = new ArrayList <Wonder>();
#PostConstruct
public void init () {
sevenNewWonders = new ArrayList <Wonder>();
sevenNewWonders.add(new Wonder("Chichen Itza", "Mexico", "http://upload.wikimedia.org/wikipedia/commons/thumb/7/7a/Chichen-Itza-Castillo-Seen-From-East.JPG/90px-Chichen-Itza-Castillo-Seen-From-East.JPG"));
sevenNewWonders.add(new Wonder("Christ the Redeemer", "Brazil", "http://upload.wikimedia.org/wikipedia/commons/thumb/5/50/CorcovadofotoRJ.jpg/90px-CorcovadofotoRJ.jpg"));
sevenNewWonders.add(new Wonder("Colosseum", "Italy", "http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Colosseum_in_Rome%2C_Italy_-_April_2007.jpg/90px-Colosseum_in_Rome%2C_Italy_-_April_2007.jpg"));
sevenNewWonders.add(new Wonder("Great Wall of China", "China", "http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/GreatWallNearBeijingWinter.jpg/90px-GreatWallNearBeijingWinter.jpg"));
sevenNewWonders.add(new Wonder("Machu Picchu", "Peru", "http://upload.wikimedia.org/wikipedia/commons/thumb/1/13/Before_Machu_Picchu.jpg/90px-Before_Machu_Picchu.jpg"));
sevenNewWonders.add(new Wonder("Petra", "Jordan", "http://upload.wikimedia.org/wikipedia/commons/thumb/0/06/PetraMonastery.JPG/90px-PetraMonastery.JPG"));
sevenNewWonders.add(new Wonder("Taj Mahal", "India", "http://upload.wikimedia.org/wikipedia/commons/thumb/c/c8/Taj_Mahal_in_March_2004.jpg/90px-Taj_Mahal_in_March_2004.jpg"));
}
public ArrayList <Wonder> getSevenNewWonders() {
return sevenNewWonders;
}
}
Wonder.java
package wonder;
public class Wonder {
public Wonder(String string, String string2, String string3) {
// TODO Auto-generated constructor stub
this.name = string;
this.location = string2;
this.imageUrl = string3;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setLocation(String location) {
this.location = location;
}
public String getLocation() {
return location;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getImageUrl() {
return imageUrl;
}
private String name;
private String location;
private String imageUrl;
}

As I understand it sorting has changed with Richfaces 4.
You will need to have a Map <String, SortOrder> and you will need to add an attribute to your rich:column where sortOrders is the above Map and vendor is the key for a given column.
sortOrder="#{bean.sortsOrders['vendor']}">
After that sorting is pretty much auto-magic, but the icon's are also not in Richfaces 4 so you will manually have to add those based on the value of the SortOrder enum for each column.
I think it is a pain and a step backwards from 3.x but that is what is needed to get sorting working.
You can always check out the RichFaces Showcase site for more info
http://showcase.richfaces.org/richfaces/component-sample.jsf?demo=extendedDataTable&sample=edt-sorting&skin=blueSky
EDIT: (Jan 2013)
With the upcoming RichFaces 4.3 Automatic Sorting is being added back in, and will include the arrows and what not. The link above should still have a good option for that.
EDIT: (Sep 2013)
RF is now in version 4.3.4 and the automatic sorting is still not back. It only works on the rich:extendedDataTable but not the rich:dataTable

Related

Trinidad 2.2.1's datatable detailstamp resolves to null when customizing the prompt facet

We're in the middle of upgrading from JSF 1.2 to 2.2 and we hit a blockade when upgrading trinidad.
In Trinidad 2.2.1, the detailstamp of a datatable will resolve to null when you're customizing the prompt facet. Anybody else knows why this happens?
This was tested on Wildfly (10.1.0.Final) with Mojarra 2.2.13.SP1, Java 8 (1.8.0_131), JSF 2.2 and Trinidad 2.2.1 (issue also exists on 2.2).
Java:
#Named
#RequestScoped
public class ProductBean {
private final AtomicBoolean seeded = new AtomicBoolean(false);
private final List<Product> products = Collections.synchronizedList(new ArrayList<>());
#PostConstruct
public void init() {
if (!seeded.get()) {
products.add(new Product(1, new ProductInfo("product 1", "1")));
products.add(new Product(2, new ProductInfo("product 2", "2")));
products.add(new Product(3, null));
seeded.set(true);
}
}
public List<Product> getProducts() {
return products;
}
public static class Product {
private final int id;
private final ProductInfo info;
public Product(int id, ProductInfo info) {
this.id = id;
this.info = info;
}
public int getId() {
return id;
}
public ProductInfo getInfo() {
return info;
}
}
public static class ProductInfo {
private final String name;
private final String code;
public ProductInfo(String name, String code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public String getCode() {
return code;
}
}
}
xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<tr:document xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:trh="http://myfaces.apache.org/trinidad/html"
xmlns:tr="http://myfaces.apache.org/trinidad"
xmlns:ui="http://java.sun.com/jsf/facelets">
<tr:page>
<tr:form id="mainForm">
<tr:table id="products" value="#{productBean.products}"
var="product">
<tr:column headerText="Id">
<tr:outputText value="#{product.id}"></tr:outputText>
</tr:column>
<tr:column headerText="Naam">
#{product.info.name}
</tr:column>
<f:facet name="detailStamp">
<f:facet name="prompt">
<tr:outputText value="Details" />
</f:facet>
#{product.id} | #{product.info.name}
</f:facet>
</tr:table>
</tr:form>
</tr:page>
</tr:document>
I'm an idiot. Trinidad works fine. The prompt facet should be outside of the detailStamp facet.
<f:facet name="detailStamp">
#{product.id} | #{product.info.name}
</f:facet>
<f:facet name="prompt">
<tr:outputText value="Details" />
</f:facet>

Nested DataTable with multiple dynamic columns display same data for each row

I would like to display some data where I need to iterate with two nested DataTables (using Mojarra 2.2.13 and Primefaces 6.0). The inner table has a dynamic amount of columns. Since the objects I need to iterate over for the columns are of two different business objects I need two separate <p:columns/> tags.
BackingBean.java
#Named
#ViewScoped
public class BackingBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Family> families;
private List<String> countries;
public void generateFamilies() {
this.families = new ArrayList<Family>();
Family f = new Family("Beta");
f.getCars().add("Mercedes");
f.getCars().add("Porsche");
f.getCars().add("VW");
f.getCars().add("Dodge");
f.getPersons().add("he");
f.getPersons().add("she");
families.add(f);
f = new Family("Alpha");
f.getCars().add("BMW");
f.getPersons().add("he");
f.getPersons().add("she");
families.add(f);
}
private void generateCountries() {
this.countries = new ArrayList<String>();
this.countries.add("Germany");
this.countries.add("England");
this.countries.add("Spain");
}
public List<Family> getFamilies() {
if (null == families) {
generateFamilies();
}
return families;
}
public List<String> getCountries() {
if (null == countries) {
generateCountries();
}
return countries;
}
public class Family {
private String name;
private List<String> persons;
private List<String> cars;
public Family(String name) {
this.name = name;
this.persons = new ArrayList<String>();
this.cars = new ArrayList<String>();
}
public String getName() {
return name;
}
public List<String> getPersons() {
return persons;
}
public List<String> getCars() {
return cars;
}
}
}
index.xthml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>DataTable BUG</title>
</h:head>
<body>
<h:form id="form">
<p:dataTable id="families" value="#{backingBean.families}" var="family">
<p:column headerText="Families">
<h3>#{family.name}</h3>
<p:dataTable id="persons" value="#{family.persons}" var="person">
<p:column headerText="Name">
Does #{person} ...
</p:column>
<p:columns value="#{family.cars}" var="car" headerText="#{car}">
... have insurance for the #{car}?
</p:columns>
<p:columns value="#{backingBean.countries}" var="country" headerText="#{country}">
... have insurance for #{country}?
</p:columns>
</p:dataTable>
</p:column>
</p:dataTable>
</h:form>
</body>
</html>
The result I get is that all inner tables (id=persons) will look the same (see image 1). The first inner table dictates the amount of columns (8 in this example). The second row of the outer table (id=families) should display only 5 columns for the inner table (only the BMW column). But is still displays all the columns from the first row. If I remove one p:columns everything works as expected (see image 2).
I looked up the documentation for p:dataTable and there seem to be no limitations that only one p:columns per p:dataTable is allowed. Am I missing something?
You are right, I can reproduce this scenario. Maybe it's a PrimeFaces bug or multiple p:columns are just not supported. As a work around you could use c:forEach for the country list:
<c:forEach items="#{backingBean.countries}" var="country">
<p:column headerText="#{country}">
... have insurance for #{country}
</p:column>
</c:forEach>

p:dataTable selected value setter doesn't work

I'm new in JSF and PrimeFaces and I can't understand why my setter for selected value doesn't set:
I've got main XHTML in which after click on <p:commandButton> I want to change selected row. But after changing selection of the row on data setter setSelectedBook() get null value on entrance.
I already set selection and rowKey for <p:dataTable>.
It looks like :
main XTML:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html"
>
<body>
<ui:composition template="./../../WEB-INF/pagesTemplate.xhtml">
<form>
<ui:define name="content">
<p:dataTable id="eventsDT" var="book" value="#{bookHolder.books}"
selectionMode= "single" selection="#{bookController.selectedBook}"
rowKey="#{book.id}">
<p:ajax event="rowSelect"/>
<p:ajax event="rowDblselect" listener="#{bookController.onDoubleRowSelect}" />
<p:column headerText="ID">
<h:outputText value="#{book.id}" />
</p:column>
<p:column headerText="Title">
<h:outputText value="#{book.longName}" />
</p:column>
</p:dataTable>
</ui:define>
<ui:define name="right">
<h:panelGrid columns="1" cellpadding="5">
<p:commandButton id="btnEdit" value="Edit"
action="#{navigationController.moveToBookEditPageSimple}"
style="width: 100px;height: 28px; margin-left: 10%"/>
</h:panelGrid>
</ui:define>
</form>
</ui:composition>
</body>
</html>
BookController that can't get value:
#Named("bookController")
#SessionScoped
#Local(BookView.class)
public class BookController implements Serializable {
public BookController() {
navigator = new NavigationController();
}
NavigationController navigator;
#Inject
BookHolder bookHolder;
private Book selectedBook;
public Book getSelectedBook() {
return selectedBook;
}
public void setSelectedBook(Book selectedBookValue) {
this.selectedBook = selectedBookValue;
}
public void onDoubleRowSelect(SelectEvent event) throws IOException {
String str = navigator.showPage("BookEdit");
FacesContext.getCurrentInstance().getExternalContext().redirect(str + ".xhtml");
}
}
BookHolderBean that contains data:
#Named("bookHolder")
#ApplicationScoped
public class BookHolder {
public BookHolder() {
}
#PostConstruct
void setValues() {
this.books = new ArrayList<>();
for (int i = 0; i < 10; i++) {
this.books.add(new Book(new ParkType(i, i,
"Book #: " + i + " (long name)",
"Book #: " + i + " (short name)",
"Book #: " + i + " (note)")));
}
}
private List<Book> books;
public List<Book> getBooks() {
return books;
}
public void setBooks(List<Book> parkTypes) {
this.books = parkTypes;
}
}
Class Book:
public class Book extends MainEntitie<Book> implements Serializable, SelectableDataModel<Book> {
#Inject
BookHolder bookHolder;
private final String longName;
private final String shortName;
public Book(BookBase sd) {
super(sd.getId(), false, false, sd.getNote());
this.longName = sd.getLongName();
this.shortName = sd.getShortName();
}
public String getLongName() {
return longName;
}
public String getShortName() {
return shortName;
}
#Override
public int getId() {
return super.getId();
}
#Override
public Object getRowKey(Book t) {
return t.getId();
}
#Override
public Book getRowData(String string) {
for (Book app : bookHolder.getBooks()) {
if (app.getId() == Integer.parseInt(string)) {
return app;
}
}
return null;
}
}
Since you use ui:define, I assume there is a ui:include in your template file (pagesTemplate.xhtml).
If so, that is great, but your included page has some unnecessary stuff, e.g. html and body tag (by the way: use h:body). No need for that.
See second part of this posting to learn how to include an xhtml file into another one.
You will notice that the content of ui:define is kind of "cut&pasted" into the your template file.
So, what about your form tag? It's being ignored (at least, I guess it won't be a parent of your datatable).
Make the h:form (again, use JSF's h:form instead of HTML form) a child of ui:define,
like:
<ui:composition template="/WEB-INF/template.xhtml"
xmlns=.....>
<ui:define name="content">
<h:form>
<p:dataTable ...>
...
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>

PrimeFaces DataTables not working

I'm new to PrimeFaces tried out an example in PrimeFaces datatable
public class Datatable {
private String fname;
private String lname;
private int age;
public Datatable(String fname, String lname, int age) {
// TODO Auto-generated constructor stub
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Here in the class I have declared what are the fields in the data table
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name="solodat")
#RequestScoped
public class Solodata implements Serializable{
private static final long serialVersionUID = 1L;
public Solodata() {}
private List<Datatable>addeta;
public List<Datatable> getAddeta() {
return addeta;
}
public void setAddeta(List<Datatable> addeta) {
this.addeta = addeta;
}
#PostConstruct
public void init() {
List<Datatable> addeta=new ArrayList<Datatable>();
addeta.add( new Datatable("man","eater",14));
addeta.add( new Datatable("solo","world",28));
addeta.add( new Datatable("antan","evanious",20));
addeta.add( new Datatable("hi","daa",29));
addeta.add( new Datatable("thallu","vandi",30));
addeta.add( new Datatable("prime","faces",1000));
addeta.add( new Datatable("crime","shit",1412));
addeta.add( new Datatable("shit","head",18));
}
}
Here in list I have get that values:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://www.java.com/jsf/html"
xmlns:f="http://www.java.com/jsf/core"
xmlns:p="http://www.primefaces.org/ui">
<h:head>
<title>DATA TABLES DEMO</title>
</h:head>
<h:body>
<h:form>
<h1>output values</h1>
<p:dataTable var="sol" value="#{solodat.addeta}" >
<p:column headerText="LASTNAME">
<h:outputText value="#{sol.lname}"/>
</p:column>
<p:column headerText="age">
<h:outputText value="#{sol.age}"/>
</p:column>
<p:column headerText="first">
<h:outputText value="#{sol.fname}"/>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
This is the xhtml page to get the bean values by data table but JSF is showing an empty page. Any help would be appreciated.
Try this and let us know (using CDI, removing the useless constructor, and initializing addeta properly)
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
#Named("solodat")
#RequestScoped
public class Solodata {
private List<Datatable> addeta;
public List<Datatable> getAddeta() {
return addeta;
}
public void setAddeta(List<Datatable> addeta) {
this.addeta = addeta;
}
#PostConstruct
public void init() {
addeta=new ArrayList<Datatable>();
addeta.add( new Datatable("man","eater",14));
addeta.add( new Datatable("solo","world",28));
addeta.add( new Datatable("antan","evanious",20));
addeta.add( new Datatable("hi","daa",29));
addeta.add( new Datatable("thallu","vandi",30));
addeta.add( new Datatable("prime","faces",1000));
addeta.add( new Datatable("crime","shit",1412));
addeta.add( new Datatable("shit","head",18));
}
}
And replace the facelet with this one (I changed the first lines)
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>DATA TABLES DEMO</title>
</h:head>
<h:body>
<h:form>
<h1>output values</h1>
<p:dataTable var="sol" value="#{solodat.addeta}" >
<p:column headerText="LASTNAME">
<h:outputText value="#{sol.lname}"/>
</p:column>
<p:column headerText="age">
<h:outputText value="#{sol.age}"/>
</p:column>
<p:column headerText="first">
<h:outputText value="#{sol.fname}"/>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
Now make sure you have placed Primefaces library at the right place, and that the app is being deployed on a running server without errors.
Edit: The reason you don't have data , is due to Datatable's constructor, which is incomplete.
Replace
public Datatable(String fname, String lname, int age) {
// TODO Auto-generated constructor stub
}
by
public Datatable(String fname, String lname, int age) {
this.fname = fname;
this.lname = lname;
this.age = age;
}
Small mistake: You are initializing a new local variable in init().
List<Datatable> addeta = new ArrayList<Datatable>();
Change it to:
this.addeta = new ArrayList<Datatable>();
You should use <!DOCTYPE html> instead of
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
and also change your are initializing as noone answer.
See also : Wrong doctype when one is specified in composite view

How do you update the page size of a PrimeFaces datatable dynamically?

I am trying to update the page size of a PrimeFaces datatable dynamically, after the datatable is displayed on the page but I can't seem to be able to do that. I am using a lazy loaded datatable if that matters... putting an EL expression in the rows attribute and doing a table refresh does not work and causes the paginator to return no data.
Any ideas if this is a bug and how to fix it?
Thanks
You need not refresh or update the datatable. Use EL expression in rowsPerPageTemplate attribute of <p:dataTable> and after loading datatable just change the rows number.
<p:dataTable value="#{managedBean.users}" var="user" lazy="true" paginator="true" rows="10" rowsPerPageTemplate="10,25 #{fn:length(managedBean.users)}">
And include this xmlns:fn="http://java.sun.com/jsp/jstl/functions" in page.
What exactly are you trying to do? This works for me (Mojarra 2.1.26, PrimeFaces 3.5):
#ManagedBean
#ViewScoped
public class Bean {
public class Item {
private String name;
public Item(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private List<Item> items;
public Bean() {
Item item1 = new Item("item1");
Item item2 = new Item("item2");
items = Arrays.asList(item1, item2);
}
public List<Item> getItems() {
return items;
}
private int tableSize = 1;
public int getTableSize() {
return tableSize;
}
public void actionSwitchSize() {
tableSize = tableSize == 1 ? 2 : 1;
}
}
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head />
<h:body>
<h:form>
<p:dataTable id="table" var="item" value="#{bean.items}"
rows="#{bean.tableSize}" paginator="true">
<p:column>
#{item.name}
</p:column>
</p:dataTable>
<p:commandButton value="switch size" action="#{bean.actionSwitchSize}"
update="table" />
</h:form>
</h:body>
</html>

Resources