Статические и динамические столбцы Primefaces в таблице данных

Я использую Primefaces 5.0 для создания динамической таблицы данных.

В моем DataObject есть несколько обязательных полей и список необязательных «tupel» (пара «ключ-значение»). Необязательный список может отличаться по размеру. Поэтому мне нужен динамический механизм для отображения списка объектов данных в Primefaces.DataTable.

Мой подход выглядит так:

public class DataObject {
    private String staticval1;
    private String staticval2;

    private List<Tupel> optionalValues;


    // .. getter, setter, hashCode, toString.....
}

public class Tupel{
    private String id;
    private String value;
}

@ManagedBean
@ViewScoped
public class TableOverviewBean {
    private List<DataObject> data;

    @EJB
    private IMyDao myDao;

    @PostConstruct
    public void init() {
        data = myDao.findAll();
    }

    public List<DataObject> getData() {
        return data;
    }

    public void setData(List<DataObject> data) {
        this.data = data;
    }
}
    <h:form>
        <p:dataTable value="#{tableOverviewBean.data}" var="data">
            <p:column headerText="static1">
                <h:outputText value="#{data.staticval1}" />
            </p:column>

            <p:column headerText="static2">
                <h:outputText value="#{data.staticval2}" />
            </p:column>

            <p:columns value="#{data.optionalValues}" var="opt" headerText="#{opt.id}">
                <h:outputText value="#{opt.value}" />
            </p:columns>
        </p:dataTable>
    </h:form>

Но это не работает. Динамические столбцы не отображаются. Как я могу решить свою проблему?

РЕДАКТИРОВАТЬ: Ожидаемый результат:

staticval1 | staticval2 | dynamic_id1 | dynamic_id2 | ... | dynmic_idn
----------------------------------------------------------------------
static1a   | static2a   | dyna_value1a| dyna_value2a | ... | dyna_valu3a
static1b   | static2b   | dyna_value1b| dyna_value2b | ... | dyna_valu3b
static1c   | static2c   | dyna_value1c| dyna_value2c | ... | dyna_valu3c

person veote    schedule 04.09.2014    source источник


Ответы (2)


Невозможно определить столбцы на основе данных строки. Представьте, что в строке 1 есть 2 столбца, в строке 2 — 6 столбцов, в строке 3 — 1 столбец и т. д. Как бы вы создали технически правильную таблицу в HTML? В каждой строке должно быть одинаковое количество столбцов.

У вас есть 2 варианта, в зависимости от того, можете ли вы изменить модель или нет:

  1. Если вы не можете изменить модель, вам нужно заменить этот <p:columns> одним <p:column> и перебрать #{data.optionalValues}, используя вложенный цикл, например. <ui:repeat> или, возможно, еще один <p:dataTable><p:columns>:

    <p:column>
        <p:dataTable value=""><!-- Empty string as value forces 1 row. -->
            <p:columns value="#{data.optionalValues}" var="opt" headerText="#{opt.id}">
                #{opt.value}
            </p:columns>
        </p:dataTable>
    </p:column>
    
  2. Если вы можете изменить модель, вам нужно, чтобы <p:columns value> указывало на свойство компонента, а не на свойство строки, чтобы оно было одинаковым для каждой строки. Это работает, если вы замените List<Tupel> optionalValues на Map<String, Tupel> optionalValues, где ключ равен Tupel#id, и добавите свойство List<String> в bean-компонент, содержащий все доступные значения Tupel#id.

    <p:columns value="#{tableOverviewBean.availableTupelIds}" var="id" headerText="#{id}">
        #{data.optionalValues[id].value}
    </p:columns>
    
person BalusC    schedule 08.09.2014
comment
Оба решения на самом деле не решают мою проблему. Я добавил пример вывода к моему вопросу. Есть ли способ получить такой стол? - person veote; 08.09.2014
comment
Вы читали 1-й абзац? Если вы хотите добиться нужного вам макета, вам нужно переместить данные из строки в bean-компонент и предоставить фиксированное количество столбцов. - person BalusC; 08.09.2014
comment
Да, я читал. Мои строки имеют одинаковое количество столбцов. Но количество столбцов может измениться, если я получу другой набор данных. Например. один раз есть 10 необязательных значений (каждый объект данных имеет 10). Другой набор может иметь 8 оптических значений. - person veote; 08.09.2014
comment
Я знаю. Но вам нужно будет изменить модель, если вы хотите получить именно тот вид, который вам нужен. Я обновил ответ. - person BalusC; 08.09.2014
comment
А как насчет значения colspan? Разве нельзя получить правильную html-таблицу с разными элементами в строке, как долго подходит значение colspan? - person opfau; 04.09.2015
comment
@opfau: colspan не меняет количество столбцов. Он только объединяет столбцы. - person BalusC; 04.09.2015
comment
Я заполнил свою модель, чтобы соответствовать одинаковому размеру столбца для каждой строки. В моем случае все строки имеют 5 столбцов. В 1-й строке есть один элемент в 1-м столбце и элемент во 2-м столбце, который определяет colspan из 3. Но он не охватывает. - person opfau; 04.09.2015

Джава:

@Named
@ViewScoped
public class LiveRangeService implements Serializable {
    private List< Map<String, ColumnModel> > tableData;
    private List<ColumnModel> tableHeaderNames;


    public List<Map<String, ColumnModel>> getTableData() {
        return tableData;
    }
    public List<ColumnModel> getTableHeaderNames() {
        return tableHeaderNames;
    }

    public void PlayListMB() {
        tableData = new ArrayList< Map<String, ColumnModel> >();

        //Generate table header.
        tableHeaderNames = new ArrayList<ColumnModel>();
        for (int j = 0; j < 5; j++) {
              tableHeaderNames.add(new ColumnModel("header "+j, " col:"+ String.valueOf(j+1)));
        }

        //Generate table data.
        for (int i = 0; i < 10; i++) {
            Map<String, ColumnModel> playlist = new HashMap<String, ColumnModel>();
            for (int j = 0; j < 5; j++) {
                playlist.put(tableHeaderNames.get(j).key,new ColumnModel(tableHeaderNames.get(j).key,"row:" + String.valueOf(i+1) +" col:"+ String.valueOf(j+1)));
            }
            tableData.add(playlist);
        }
    }

    static public class ColumnModel implements Serializable {

        private String key;
        private String value;

        public ColumnModel(String key, String value) {
            this.key = key;
            this.value = value;
        }

        public String getKey() {
            return key;
        }

        public String getValue() {
            return value;
        }
    }

И XHTML:

                <h:form>

                    <p:dataTable id="tbl" var="result"
                        value="#{liveRangeService.tableData}"
                        rendered="#{not empty liveRangeService.tableData}"
                        rowIndexVar="rowIndex"
                        >

                        <f:facet name="header">  header table </f:facet>

                        <p:column>
                            <f:facet name="header">
                                <h:outputText value="序号" />
                            </f:facet>
                            <h:outputText value="#{rowIndex+1}" />
                        </p:column>

                        <p:columns value="#{liveRangeService.tableHeaderNames}"
                            var="mycolHeader" columnIndexVar="colIndex">
                            <f:facet name="header">
                                <h:outputText value="#{mycolHeader.value}" />

                            </f:facet>
                            <h:outputText value="#{result[mycolHeader.key].value}" />
                            <br />
                        </p:columns>

                    </p:dataTable>
                </h:form>

Это пример.

person Zhi Bin    schedule 12.05.2016