3

I have to show multiple dynamic number of primefaces datatables with dynamic columns on single page. Everything works fine if number of columns in each dynamic datatable is same.

Wrong behaviour occurs when there are different number of columns in different tables. All the tables show as many columns as in the first table in the list.

Tested on:

  • Primefaces: 3.4 and 4.0
  • JSF 2.0

Here is the code demonstrating the problem:

EDIT: The following code is assigning different number of columns to different tables. The first table should have 8 columns, second should have 7 columns, and so on. But all the tables take up 8 columns; i.e. they take the number of columns from first table.

Expected Output: 5 datatables. First table having 8 columns, Second table 7 columns, Third table 6 columns, and so on. Expected Output Screenshot -- This is actually the output on pf 3.3

Actual Output: 5 tables, all having 8 columns. Data shown is correct. But empty extra columns are also being shown, which should not be shown. Actual Output Screenshot

test2.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:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">

<f:view contentType="text/html">
    <h:head>
    </h:head>

    <h:body>

        <h:form>

            <ui:repeat value="#{tableBean.tables}" var="table">

                <p:dataTable id="cars" var="car" value="#{table.carsSmall}"
                    style="font-size: 12px;'width: 70%;">
                    <p:columns value="#{table.columns}" var="column"
                        columnIndexVar="colIndex">
                        <f:facet name="header">  
                #{column.header}  
            </f:facet>

                        <h:outputText value="#{car[column.property]}"></h:outputText>
                    </p:columns>

                </p:dataTable>

                <br />
            </ui:repeat>

        </h:form>

    </h:body>



</f:view>
</html>

TableBean.java:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean(name = "tableBean")
@ViewScoped
public class TableBean implements Serializable
{
    private static final long serialVersionUID = 1L;
    private final static List<String> VALID_COLUMN_KEYS = Arrays.asList("model", "manufacturer", "year", "color");
    private final static String[] colors;
    private final static String[] manufacturers;
    private String columnTemplate = "model manufacturer year";

    static
    {
        colors = new String[10];
        colors[0] = "Black";
        colors[1] = "White";
        colors[2] = "Green";
        colors[3] = "Red";
        colors[4] = "Blue";
        colors[5] = "Orange";
        colors[6] = "Silver";
        colors[7] = "Yellow";
        colors[8] = "Brown";
        colors[9] = "Maroon";

        manufacturers = new String[10];
        manufacturers[0] = "Mercedes";
        manufacturers[1] = "BMW";
        manufacturers[2] = "Volvo";
        manufacturers[3] = "Audi";
        manufacturers[4] = "Renault";
        manufacturers[5] = "Opel";
        manufacturers[6] = "Volkswagen";
        manufacturers[7] = "Chrysler";
        manufacturers[8] = "Ferrari";
        manufacturers[9] = "Ford";
    }

    private List<Car> carsSmall;
    private List<ColumnModel> columns = new ArrayList<ColumnModel>();;

    private List<TableBean> tables;

    public List<TableBean> getTables()
    {
        if (tables == null)
        {
            tables = new ArrayList<TableBean>();
            for (int i = 0; i < 5; i++)
            {
                TableBean t = new TableBean();

                for (int j = 5; j > i; j--)
                {
                    t.columnTemplate += " year";
                    t.createDynamicColumns();
                }
                tables.add(t);
            }
        }

        return tables;
    }

    public TableBean()
    {
        carsSmall = new ArrayList<Car>();

        populateRandomCars(carsSmall, 9);

        createDynamicColumns();
    }

    private void populateRandomCars(List<Car> list, int size)
    {
        for (int i = 0; i < size; i++)
            list.add(new Car(getRandomModel(), getRandomYear(), getRandomManufacturer(), getRandomColor()));
    }

    public List<Car> getCarsSmall()
    {
        return carsSmall;
    }

    private int getRandomYear()
    {
        return (int) (Math.random() * 50 + 1960);
    }

    private String getRandomColor()
    {
        return colors[(int) (Math.random() * 10)];
    }

    private String getRandomManufacturer()
    {
        return manufacturers[(int) (Math.random() * 10)];
    }

    private String getRandomModel()
    {
        return UUID.randomUUID().toString().substring(0, 8);
    }

    public List<ColumnModel> getColumns()
    {
        return columns;
    }

    public String[] getManufacturers()
    {
        return manufacturers;
    }

    public String[] getColors()
    {
        return colors;
    }

    static public class ColumnModel implements Serializable
    {
        private static final long serialVersionUID = 1L;
        private String header;
        private String property;

        public ColumnModel(String header, String property)
        {
            this.header = header;
            this.property = property;
        }

        public String getHeader()
        {
            return header;
        }

        public String getProperty()
        {
            return property;
        }

        @Override
        public String toString()
        {
            return "[header=" + header + ", property=" + property + "]";
        }
    }

    public void createDynamicColumns()
    {
        String[] columnKeys = columnTemplate.split(" ");
        columns.clear();

        for (String columnKey : columnKeys)
        {
            String key = columnKey.trim();

            if (VALID_COLUMN_KEYS.contains(key))
            {
                columns.add(new ColumnModel(columnKey.toUpperCase(), columnKey));
            }
        }
    }
}

Car.java:

import java.io.Serializable;

public class Car implements Serializable
{
    private static final long serialVersionUID = 1L;
    private String model;
    private int year;
    private String manufacturer;
    private String color;

    public Car(String model, int year, String manufacturer, String color)
    {
        super();
        this.model = model;
        this.year = year;
        this.manufacturer = manufacturer;
        this.color = color;
    }

    public String getModel()
    {
        return model;
    }

    public void setModel(String model)
    {
        this.model = model;
    }

    public int getYear()
    {
        return year;
    }

    public void setYear(int year)
    {
        this.year = year;
    }

    public String getManufacturer()
    {
        return manufacturer;
    }

    public void setManufacturer(String manufacturer)
    {
        this.manufacturer = manufacturer;
    }

    public String getColor()
    {
        return color;
    }

    public void setColor(String color)
    {
        this.color = color;
    }

}
9
  • I was not able to understand your problem. You column template contains model manufacturer year and it is very obvious that if you do this with a Table class object t.columnTemplate += " year"; it will add the column year to it. That is how it should behave and that is the way it is behaving. Please make us understand what you want to do? Commented Jan 24, 2014 at 10:24
  • @VinayakPingale Actually t.columnTemplate += " year" is in loop. It appends 5 extra columns in first table, 4 extra columns in second table, 3 extra columns in third table and so on. Thus the first table should have 8 columns, second should have 7 columns, and so on. But all the tables take up 8 columns. Commented Jan 24, 2014 at 10:54
  • PS: This is test code, not the actual code. This is just here so that anyone can copy and paste and run this code right away to see the output. Commented Jan 24, 2014 at 10:59
  • So you want to say every table on the screen of yours contains 8 column? Commented Jan 24, 2014 at 11:04
  • Yes. Every table is taking upto 8 columns. The extraneous columns in each table are empty. In another scenario, when first table has 3 columns and second has 4, then second only shows 3 columns. Thus my point is, each table takes number of columns from first table. Commented Jan 24, 2014 at 11:07

1 Answer 1

2

I think you should use Primefaces 3.3 because it is showing as expected as in my case. For now this will work but i will try to get this fixed on Primefaces 4.0 too.

Please find attached image for the same. Image

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.