【问题标题】:Primefaces 8.0 Datatable with Dynamic Model and Columns具有动态模型和列的 Primefaces 8.0 数据表
【发布时间】:2020-09-17 02:06:23
【问题描述】:

我有一个 primefaces 数据表,它显示来自多个数据库表的数据。选择列表允许用户选择要显示的特定数据库表。它按预期工作,除非使用 dataTable 过滤功能。例如,当用户从选择列表中选择“DEPT”时,dataTable 将使用 DEPT 表中的数据呈现。用户可以正常选择其他表。但是,如果用户在过滤后选择另一个名为“EMP”的表,则 dataTable 无法呈现,并出现以下异常:

javax.el.PropertyNotFoundException: The class 'example.dto.Dept' does not have the property 'firstName'.
at javax.el.BeanELResolver.getBeanProperty(BeanELResolver.java:576)
at javax.el.BeanELResolver.getValue(BeanELResolver.java:291)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:156)

这是 .xhtml 文件:

<h:form prependId="false">

    <p:outputLabel for="selTbl" value="Select a table:" />
    <p:autoComplete id="selTbl" value="#{mainBean.selectedTable}"
        completeMethod="#{mainBean.filterAuditTables}" cache="true" dropdown="true" effect="fade"
        minQueryLength="3" forceSelection="true" size="35" style="margin-left: 10px;">
        <p:ajax event="itemSelect" listener="#{mainBean.onTableSelect}" process="@this" update="@form" />
    </p:autoComplete>

    <p:dataTable id="audTblData" value="#{mainBean.data}" var="row"
        filteredValue="#{mainBean.filteredData}" resizableColumns="true" resizeMode="expand"
        sortMode="multiple">

        <f:facet name="header">
            <h:outputText value="#{mainBean.selectedTable}" />
        </f:facet>

        <p:columns value="#{mainBean.tableColumns}" var="col" sortBy="#{row[col.property]}"
            filterBy="#{row[col.property]}" filterMatchMode="contains">
            <f:facet name="header">
                <h:outputText value="#{col.header}" />
            </f:facet>
            <h:outputText value="#{row[col.property]}" />
        </p:columns>

    </p:dataTable>

</h:form>

MainBean.java:

@Named
@ViewScoped
public class MainBean implements Serializable {

    private static final long serialVersionUID = 1L;

    // these are used for the audited table selection list
    private List<String> auditedTables;
    private String selectedTable;

    // these are used in the table that displays the audit data
    private List<ColumnModel> tableColumns;
    private List<Auditable> data;
    private List<Auditable> filteredData;

    @Inject
    private AudviewService audviewService;

    @PostConstruct
    public void init() {
        auditedTables = audviewService.getAuditedTables();
    }

    public List<String> filterAuditTables(String query) {
        return auditedTables
                .stream()
                .filter(t -> t.contains(query.toUpperCase()))
                .collect(Collectors.toList());
    }

    public void onTableSelect(SelectEvent<String> event) {
        retrieveTableData();
    }

    public void retrieveTableData() {

        List<String> columns = audviewService.listTableColumns(selectedTable);

        // initialize columns for <p:dataTable>
        tableColumns = new ArrayList<ColumnModel>();
        for (String col : columns) {
            tableColumns.add(new ColumnModel(col, AudviewUtil.columnToProperty(col)));
        }

        // retrieve data for the selected table
        data = audviewService.getTableData(selectedTable);
    }

    /* getters and setters */
}

注意 Auditable 是 Dept.java 和 Emp.java 实现的接口。

【问题讨论】:

  • 你能发布你的 mainBean 定义吗?
  • 我已将 mainBean 添加到原帖中。
  • 要查看我是否正确理解问题,您必须显示扩展 Auditable 类的不同对象列表,并在切换时出现错误?将所有显示的字段移到超类中是不是正确的选项?
  • 是的,没错。我宁愿不将所有显示的字段移到超类中。大约有。 200 个子类。当新模型类包含前一个类没有的属性时,会发生切换时的错误。同样,这仅在实际使用 中的过滤功能时才发生。如果用户没有输入任何过滤约束,切换到不同的列表就可以了。
  • 如果你使用lazyDataModel/

标签: datatable primefaces dynamic-columns


【解决方案1】:

如您所见,如果过滤或排序的列是不在新选定类中的字段,则问题是从过滤或排序的数据表切换到另一个。一个简单的解决方案是将所有需要的字段移动到超类Auditable

另一种方法是将数据表重置和更新分两步分离,这是一个可能的解决方案(出于测试目的,我将您的服务替换为静态代码,因此在使我的解决方案适应您的代码时可能会出现一些错误):

xhtml

<h:form id="formTbl" prependId="false">

    <p:outputLabel for="selTbl" value="Select a table:" />
    <p:autoComplete id="selTbl" value="#{mainBean.selectedTable}"
        completeMethod="#{mainBean.filterAuditTables}" cache="true"
        dropdown="true" effect="fade" minQueryLength="3"
        forceSelection="true" size="35" style="margin-left: 10px;">
        <p:ajax event="itemSelect" listener="#{mainBean.onTableSelect}"
            process="@this" onstart="PF('vtWidget').clearFilters()" />
    </p:autoComplete>
    <p:remoteCommand name="btn" process="@this" update="audTblData" />

    <p:dataTable id="audTblData" value="#{mainBean.data}" var="row"
        filteredValue="#{mainBean.filteredData}" resizableColumns="true"
        resizeMode="expand" sortMode="multiple" widgetVar="vtWidget">

        <f:facet name="header">
            <h:outputText value="#{mainBean.selectedTable}" />
        </f:facet>

        <p:columns value="#{mainBean.tableColumns}" var="col"
            sortBy="#{row[col.property]}" filterBy="#{row[col.property]}"
            filterMatchMode="contains">
            <f:facet name="header">
                <h:outputText value="#{col.header}" />
            </f:facet>
            <h:outputText value="#{row[col.property]}" />
        </p:columns>

    </p:dataTable>

</h:form>

java

public void retrieveTableData() {

    List<String> columns = listTableColumns(selectedTable);

    // initialize columns for <p:dataTable>
    tableColumns = new ArrayList<ColumnModel>();
    for (String col : columns) {
        tableColumns.add(new ColumnModel(col + " header", col));
    }

    // retrieve data for the selected table
    data = getData(selectedTable);
    DataTable dataTable = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent("formTbl:audTblData");
    if (dataTable != null) {
        dataTable.reset();
    }
    PrimeFaces.current().executeScript("btn()");
}

注意,如果您还需要管理分页。

【讨论】:

  • 谢谢!我的初步测试表明该修复程序有效。使用表格过滤器后选择另一个表格时不再出现问题。但是,columnToggler 不再起作用……仅供参考。我会看看我是否能找出原因。
  • 对任何对此用例感兴趣的其他人的最终更新...该修复不需要 xhtml 文件中的 标记或“PrimeFaces.current().executeScript( "btn()")"; MainBean.java 中的行。当我删除这两行时, 再次工作。再次感谢 WoAiNii 的解决方案!
猜你喜欢
  • 2014-02-15
  • 2011-10-23
  • 2013-02-17
  • 1970-01-01
  • 2019-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多