首页 文章

根据PrimeFaces LazyDataModel <T>返回的行数渲染JSF / PrimeFaces组件

提问于
浏览
3

我需要根据PrimeFaces LazyDataModel<T> 返回的行数渲染一些组件 .

例如,只有当关联的惰性数据模型返回至少一行时,才应呈现 <p:panelGrid> .

<p:panelGrid rendered=#{bean.rowCount gt 0}>

    ...
    ...
    ...

</p:panelGrid>

在下面给出一个懒惰的 <p:dataList> .

<p:dataList var="row"
            value="#{bean}"
            first="0"
            rows="10"
            paginator="true"
            lazy="true">

            ...
            ...
            ...

<p:dataList>

beans 很常见:

@Named
@ViewScoped
public class Bean extends LazyDataModel<Entity> implements Serializable
{
    @Inject
    private BeanService service;
    private static final long serialVersionUID = 1L;

    @Override
    public List<Entity> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters)
    {
        setRowCount(service.rowCount());
        return service.getList(first, pageSize);
    }    
}

当处理 <p:panelGrid>rendered 属性时,由于惰性数据模型不可用,将不再呈现给定的 <p:panelGrid> .

正确的事情可能发生,如果 <p:panelGrid><p:dataList> 的顺序互换,但这是一个设计问题,无法想到 .

给定的 <p:dataList> 包含用于预览的复杂报告数据列表(与 <p:dataTable><p:panelGrid> 和其他一些组合),然后将其导出到MS-Excel工作簿并下载文件 .

报告数据列表(由 <p:dataList> 持有)取决于由 <p:inputText><p:selectOneMenu> 等组成的几个(自定义)过滤器 . 列表是基于过滤器值/事件更新的AJAX .

根据过滤器的值,列表可以随时为空 . 在任何情况下,如果 <p:dataList> 为空,则不得渲染 <p:panelGrid><p:panelGrid> 只是一个简单的例子 . 还有其他组件) .

如何根据 LazyDataModel<T> (最终来自关联数据库)返回的行数来呈现此类组件,而无需执行额外JPA查询的额外开销来计算可根据过滤器的值返回的行数(当时存在已经非常复杂/昂贵的报告正在执行JPA标准查询)?

3 回答

  • 1

    load 中设置行计数时,您可能会移动

    setRowCount(service.rowCount());
    

    在加载之前执行的方法(或在行计数的getter中作为最后一种可能性),因为我假设 service.rowCount() 不执行加载本身,或者我错了?

  • 1

    您的代码问题是您定义模型的方式 . 由于您定义的Bean类,除非由 <p:dataList> 调用,否则不会设置模型行号

    我能提供的最好的东西就是有一个 beans 子并且里面有模型 . 这样的事情:

    public class MainBean {
        private SERVICE service;
        private SEARCHOBJECT searchObject;
    
        private BaseListDataModel<LISTMODEL> dataModel = new BaseListDataModel<LM>() {
            @Override
            public List<LM> load(int first,
                                 int pageSize,
                                 String sortField,
                                 SortOrder sortOrder,
                                 Map<String, String> filters) {
                List<LM> result = new ArrayList<LM>();
                try {
                    searchObject.setStartIndex(first);//this is used for my own business, you can handle the paging in some other way
                    searchObject.setPageSize(pageSize);//this is used for my own business, you can handle the paging in some other way
                    result = getService().search(searchObject);
                    int rowCount = searchObject.getTotalRecordCount();
                    this.setRowCount(rowCount);
                } catch (BusinessException ex) {
                    log.error(ex.getMessage(), ex);
                    saveError(ex);
                } catch (Exception ex) {
                    log.error(ex.getMessage(), ex);
                    saveError(new UnknownSystemException(ex));
                }
                return result;
            }
        };
    
        ...
    }
    

    我希望这是有帮助的 .

  • 1

    列表和数据表的示例 . 表“更改数据”没有ajax事件 . 但是当你做一些过滤,排序或其他只刷新表时,你就是用ajax做的 . 所以你可以监视ajax调用,当ajax调用发生时你可以刷新你的列表 . 这里的工作代码(琐碎的例子):

    请注意,这不是更新上部列表的命令按钮,您可以使用任何其他ajax命令更改数据表并仍然可以工作

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://xmlns.jcp.org/jsf/html"
          xmlns:f="http://xmlns.jcp.org/jsf/core"
          xmlns:pe="http://primefaces.org/ui/extensions"
          xmlns:p="http://primefaces.org/ui" >
    <pe:head title="PrimeFaces Extensions - ShowCase">
        <f:facet name="first">
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        </f:facet>
    </pe:head>
    <f:view>
        <h:form>
            <h:panelGrid id="pvis" >
                <p:dataList value="#{modelBean.data2}" var="d" rendered="#{ modelBean.data.size() > 0}" >
                    #{d}|
                </p:dataList>
            </h:panelGrid>
            <p:remoteCommand name="updatelist" update="pvis" />
            <p:ajaxStatus onsuccess="updatelist();" />
            <p:dataTable value="#{modelBean.data}" var="d" id="table"  >
                <p:remoteCommand update="pvis" autoRun="true" immediate="true" />
    
                <p:column headerText="Value" >
                    <p:outputLabel value="#{d}" />
                </p:column>
            </p:dataTable>
            <p:commandButton action="#{modelBean.addRandomData()}" update="table" value="Populate" />
        </h:form>
    </f:view>
    </html>
    

    托管bean:

    package com.example.stackoverflow;
    
        import javax.annotation.PostConstruct;
        import javax.enterprise.context.SessionScoped;
        import javax.inject.Named;
        import java.io.Serializable;
        import java.util.ArrayList;
        import java.util.List;
        import java.util.Random;
    
            @Named
            @SessionScoped
            public class ModelBean implements Serializable {
    
                private List<String> data = new ArrayList<String>();
                private List<String> data2 = new ArrayList<String>();
    
                public List<String> getData() {
                    return data;
                }
    
                public void setData(List<String> data) {
                    this.data = data;
                }
    
                public List<String> getData2() {
                    return data2;
                }
    
                public void setData2(List<String> data2) {
                    this.data2 = data2;
                }
    
                @PostConstruct
                public void init() {
                    for (int i = 0;i < 10;i++) {
                        Random random = new Random();
                        data2.add("value:"+random.nextInt());
                    }
                }
    
                public void addRandomData() {
                    for (int i = 0;i < 10;i++) {
                        Random random = new Random();
                        data.add("value:"+random.nextInt());
                    }
                }
            }
    

    根据您的评论:

    我还是找不到办法 . 当要连续生成报告列表时,数据表不适合报告

    我添加以下解决方案:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://xmlns.jcp.org/jsf/html"
          xmlns:f="http://xmlns.jcp.org/jsf/core"
          xmlns:pe="http://primefaces.org/ui/extensions"
          xmlns:p="http://primefaces.org/ui" >
    <pe:head title="PrimeFaces Extensions - ShowCase">
        <f:facet name="first">
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        </f:facet>
    </pe:head>
    <f:view>
        <h:form>
    
            <p:outputPanel deferred="true" deferredMode="load" >
                <p:panelGrid rendered="#{modelBean.rowCount > 0}" columns="1" >
                    Show me only if Lazy Model has row
                </p:panelGrid>
            </p:outputPanel>
    
            <p:dataList  value="#{modelBean}" lazy="true" var="d" type="unordered" itemType="none" paginator="true" rows="10" styleClass="paginated" >
                <f:facet name="header">
                    Base list
                </f:facet>
                #{d}
            </p:dataList>
    
    
    
        </h:form>
    </f:view>
    </html>
    

    和懒惰的模型:

    @Named
    @SessionScoped
    public class ModelBean extends LazyDataModel<String> implements Serializable {
    
        private List<String> data = new ArrayList<String>();
        private List<String> data2 = new ArrayList<String>();
    
        public List<String> getData() {
            return data;
        }
    
        public void setData(List<String> data) {
            this.data = data;
        }
    
        public List<String> getData2() {
            return data2;
        }
    
        public void setData2(List<String> data2) {
            this.data2 = data2;
        }
    
        @PostConstruct
        public void init() {
            for (int i = 0;i < 10;i++) {
                Random random = new Random();
                data2.add("value:"+random.nextInt());
            }
        }
    
        /*public void addRandomData() {
            for (int i = 0;i < 10;i++) {
                Random random = new Random();
                data.add("value:"+random.nextInt());
            }
        }*/
    
    
    
        @Override
        public List<String> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, Object> filters) {
            data = new ArrayList<String>();
            for (int i = 0;i < pageSize;i++) {
                Random random = new Random();
                data.add("value:"+random.nextInt());
            }
    
            setRowCount(100);
            return data;
        }
    
        @Override
        public List<String> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
            data = new ArrayList<String>();
            for (int i = 0;i < pageSize;i++) {
                Random random = new Random();
                data.add("value:"+random.nextInt());
            }
    
            setRowCount(100);
            return data;
        }
    }
    

    请注意可选渲染的延迟加载(使用输出面板) .

    另一种解决方案是运行远程命令,以更新页面末尾的第一个面板 .

    Note: to make visible a render false, you have to update the parent of that element

相关问题