Columns of datatable can be created dynamically using the p:columns component.
<div class="card">
Available columns are <b>name</b>, <b>country</b>, <b>date</b>, <b>status</b> and <b>activity</b>.
<h:form id="form">
<div class="mt-3 mb-5">
<p:inputText id="template" value="#{dtColumnsView.columnTemplate}" size="50" styleClass="mr-2"/>
<p:commandButton update="customers" action="#{dtColumnsView.updateColumns}" value="Update"
process="@parent" icon="pi pi-refresh"
oncomplete="PF('customersTable').clearFilters()"/>
</div>
<p:dataTable id="customers" var="customer" value="#{dtColumnsView.customers}" widgetVar="customersTable"
filteredValue="#{dtColumnsView.filteredCustomers}">
<p:columns value="#{dtColumnsView.columns}" var="column" headerText="#{column.header}" field="#{column.property}">
<f:facet name="filter">
<p:datePicker selectionMode="range" converter="javax.faces.DateTime" onchange="PF('customersTable').filter()" rendered="#{column.type eq 'date'}"/>
<p:selectOneMenu onchange="PF('customersTable').filter()" rendered="#{column.type eq 'enum'}">
<f:selectItem itemValue="#{null}" itemLabel=""/>
<f:selectItems value="#{column.klazz.enumConstants}" />
</p:selectOneMenu>
</f:facet>
</p:columns>
</p:dataTable>
</h:form>
</div>
@Named("dtColumnsView")
@ViewScoped
public class ColumnsView implements Serializable {
private String columnTemplate = "name country date status activity";
private List<ColumnModel> columns;
private List<Customer> customers;
private List<Customer> filteredCustomers;
private Map<String, Class> validColumns;
@Inject
private CustomerService service;
@PostConstruct
public void init() {
customers = service.getCustomers(10);
validColumns = Stream.of(Customer.class.getDeclaredFields()).collect(Collectors.toMap(Field::getName, Field::getType));
createDynamicColumns();
}
public void setColumns(List<ColumnModel> columns) {
this.columns = columns;
}
public List<Customer> getCustomers() {
return customers;
}
public void setCustomers(List<Customer> customers) {
this.customers = customers;
}
public List<Customer> getFilteredCustomers() {
return filteredCustomers;
}
public void setFilteredCustomers(List<Customer> filteredCustomers) {
this.filteredCustomers = filteredCustomers;
}
public CustomerService getService() {
return service;
}
public void setService(CustomerService service) {
this.service = service;
}
public String getColumnTemplate() {
return columnTemplate;
}
public void setColumnTemplate(String columnTemplate) {
this.columnTemplate = columnTemplate;
}
public List<ColumnModel> getColumns() {
return columns;
}
private void createDynamicColumns() {
String[] columnKeys = columnTemplate.split(" ");
columns = new ArrayList<>();
for (String columnKey : columnKeys) {
String key = columnKey.trim();
if (validColumns.containsKey(key)) {
columns.add(new ColumnModel(columnKey.toUpperCase(), columnKey, validColumns.get(key)));
}
}
}
public void updateColumns() {
//reset table state
DataTable table = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent(":form:customers");
table.resetColumns();
//update columns
createDynamicColumns();
}
public static class ColumnModel implements Serializable {
private String header;
private String property;
private String type;
private Class<?> klazz;
public ColumnModel(String header, String property, Class klazz) {
this.header = header;
this.property = property;
this.klazz = klazz;
initType();
}
public String getHeader() {
return header;
}
public String getProperty() {
return property;
}
public String getType() {
return type;
}
public Class<?> getKlazz() {
return klazz;
}
private void initType() {
if (Temporal.class.isAssignableFrom(klazz)) {
type = "date";
}
else if (klazz.isEnum()) {
type = "enum";
}
}
}
}
@Named
@ApplicationScoped
public class CustomerService {
private Random random = new SecureRandom();
private Country[] countries;
private Representative[] representatives;
private String[] firstNames;
private String[] lastNames;
private String[] companies;
@PostConstruct
public void init() {
countries = new Country[]{
new Country(0, "Argentina", "ar"),
new Country(1, "Australia", "au"),
new Country(2, "Brazil", "br"),
new Country(3, "Canada", "ca"),
new Country(4, "Germany", "de"),
new Country(5, "France", "fr"),
new Country(6, "India", "in"),
new Country(7, "Italy", "it"),
new Country(8, "Japan", "jp"),
new Country(9, "Russia", "ru"),
new Country(10, "Spain", "es"),
new Country(11, "United Kingdom", "gb")};
companies = new String[]{"Benton, John B Jr", "Chanay, Jeffrey A Esq", "Chemel, James L Cpa", "Feltz Printing Service",
"Printing Dimensions", "Chapman, Ross E Esq", "Morlong Associates", "Commercial Press", "Truhlar And Truhlar Attys",
"King, Christopher A Esq", "Dorl, James J Esq", "Rangoni Of Florence", "Feiner Bros", "Buckley Miller Wright",
"Rousseaux, Michael Esq"};
representatives = new Representative[]{
new Representative("Amy Elsner", "amyelsner.png"),
new Representative("Anna Fali", "annafali.png"),
new Representative("Asiya Javayant", "asiyajavayant.png"),
new Representative("Bernardo Dominic", "bernardodominic.png"),
new Representative("Elwin Sharvill", "elwinsharvill.png"),
new Representative("Ioni Bowcher", "ionibowcher.png"),
new Representative("Ivan Magalhaes", "ivanmagalhaes.png"),
new Representative("Onyama Limba", "onyamalimba.png"),
new Representative("Stephen Shaw", "stephenshaw.png"),
new Representative("Xuxue Feng", "xuxuefeng.png")};
firstNames = new String[]{"James", "David", "Jeanfrancois", "Ivar", "Tony",
"Adams", "Claire", "Costa", "Juan", "Maria", "Jennifer",
"Stacey", "Leja", "Morrow", "Arvin", "Darci", "Izzy",
"Ricardo", "Clifford", "Emily", "Kadeem", "Mujtaba", "Aika",
"Mayumi", "Misaki", "Silvio", "Nicolas", "Antonio",
"Deepesh", "Aditya", "Aruna", "Jones", "Julie", "Smith",
"Johnson", "Francesco", "Salvatore", "Kaitlin", "Faith",
"Maisha", "Jefferson", "Leon", "Rodrigues", "Alejandro",
"Munro", "Cody", "Chavez", "Sinclair", "Isabel", "Octavia",
"Murillo", "Greenwood", "Wickens", "Ashley"};
lastNames = new String[]{"Butt", "Darakjy", "Venere", "Paprocki", "Foller",
"Morasca", "Tollner", "Dilliard", "Wieser", "Marrier", "Amigon",
"Maclead", "Caldarera", "Ruta", "Albares", "Poquette", "Garufi",
"Gaucho", "Rim", "Whobrey", "Flosi", "Nicka", "Inouye",
"Kolmetz", "Royster", "Slusarski", "Iturbide", "Caudy",
"Chui", "Kusko", "Figeroa", "Vocelka", "Stenseth", "Glick",
"Sergi", "Shinko", "Stockham", "Ostrosky", "Gillian",
"Rulapaugh", "Schemmer", "Oldroyd", "Campain", "Perin",
"Ferencz", "Saylors", "Briddick", "Waycott", "Bowley", "Malet",
"Malet", "Bolognia", "Nestle", "Doe"};
}
public List<Customer> getCustomers(int number) {
List<Customer> customers = new ArrayList<>();
for (int i = 0; i < number; i++) {
customers.add(
new Customer(i + 1000, getName(), getCompany(), getCountry(), getDate(),
CustomerStatus.random(), getActivity(), getRepresentative()));
}
return customers;
}
public List<Country> getCountries() {
return Arrays.asList(countries);
}
public CustomerStatus[] getCustomerStatus() {
return CustomerStatus.values();
}
public List<Representative> getRepresentatives() {
return Arrays.asList(representatives);
}
private String getName() {
return firstNames[random.nextInt(firstNames.length)] + Constants.SPACE
+ (char) (random.nextInt(26) + 'A') + Constants.SPACE
+ lastNames[random.nextInt(lastNames.length)];
}
private Country getCountry() {
return countries[random.nextInt(countries.length)];
}
private String getCompany() {
return companies[random.nextInt(companies.length)];
}
private LocalDate getDate() {
LocalDate now = LocalDate.now();
long randomDay = ThreadLocalRandom.current().nextLong(now.minusDays(30).toEpochDay(), now.toEpochDay());
return LocalDate.ofEpochDay(randomDay);
}
private int getActivity() {
return random.nextInt(100);
}
private Representative getRepresentative() {
return representatives[random.nextInt(representatives.length)];
}
}