p:带自定义过滤器的dataTable:无法转换为ValueHolder异常

时间:2018-03-29 16:33:33

标签: primefaces jsf-2

我尝试为我的primefaces数据表实现自定义过滤器。我想用树组件过滤datetring。这是一个截图: Custom DataTable filter with Tree component

这是我的专栏定义。

<p:column filterBy="#{company.datum_wiedervorlage}" filterMatchMode="in" filterFunction="#{searchAndSelectView.filterByDatumWiedervorlage}">
    <f:facet name="header">
        <h:outputText style="width:150px" id="wiedervorlage_header" styleClass="single-ui-column-title" value="Datum Wiedervorlage" />
    </f:facet>
    <f:facet name="filter">
        <p:overlayPanel for="wiedervorlage_header" hideEffect="fade" style="position: fixed" id="overlay_filter">
            <p:tree value="#{searchAndSelectView.datumWiedervorlageTree}" var="entry" selectionMode="checkbox" animate="true" filterBy="#{entry}" selection="#{searchAndSelectView.selectedTreeNodeDates}">
                <p:ajax event="select" update=":form" listener="#{searchAndSelectView.onTreeNodeDateSelect}"/>
                    <p:treeNode>
                        <h:outputText value="#{entry}" />
                    </p:treeNode>
            </p:tree>
        </p:overlayPanel>
    </f:facet>
    <p:cellEditor>
        <f:facet name="output">
            <h:outputText value="#{company.datum_wiedervorlage}" />
        </f:facet>
        <f:facet name="input">
            <p:inputText id="datum_wiedervorlage_input" value="#{company.datum_wiedervorlage}" style="width:100%" />
        </f:facet>
    </p:cellEditor>
</p:column>

问题是我每次想要过滤其他列时都会遇到以下异常。

18:11:04,288 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-126) java.lang.ClassCastException: org.primefaces.component.overlaypanel.OverlayPanel cannot be cast to javax.faces.component.ValueHolder
at org.primefaces.component.datatable.feature.FilterFeature.populateFilterMetaDataWithoutColumnGroups(FilterFeature.java:396)
at org.primefaces.component.datatable.feature.FilterFeature.populateFilterMetaData(FilterFeature.java:293)
at org.primefaces.component.datatable.feature.FilterFeature.decode(FilterFeature.java:93)
at org.primefaces.component.datatable.DataTable.processValidators(DataTable.java:847)
at com.sun.faces.context.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:575)
at com.sun.faces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:183)
at org.primefaces.component.api.UIData.visitTree(UIData.java:827)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIForm.visitTree(UIForm.java:362)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at javax.faces.component.UIComponent.visitTree(UIComponent.java:1700)
at com.sun.faces.context.PartialViewContextImpl.processComponents(PartialViewContextImpl.java:403)
at com.sun.faces.context.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:266)
at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:57)
at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1193)
at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:805)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

我没有胶水如何解决这个问题。我尝试使用InputHidden字段组件修复它,但没有任何运气。 Primefaces datatable date range filter with filterFunction

有人知道让这件事发挥作用的可能方法吗?

修改:根据要求提供。我正在使用primefaces 6.1和JSF 2.1

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。我已经自定义了OutputPanel,OverlayPanel和Tree,以允许创建我的自定义过滤器。对于我所有的新类,我都扩展了Primefaces类并实现了ValueHolder接口。我自定义的组件是:filterOutputPanel,overlayFilterPanel和TreeFilter。

代码如下:

<p:column id="dataDocColumn" filterBy="#{row.documentDate}"
          headerText="Document date" filterMatchMode="equals" sortBy="#{row.documentDate}" >
    <f:facet name="filter">
        <cf:filterOutputPanel deferred="true">
            <p:commandButton id="filterBtn" value="Filter" />
            <cf:overlayFilterPanel for="filterBtn" hideEffect="fade" style="text-align:left;">
                <cf:treeFilter id="dataDocTree"
                                value="#{myBean.rootDataDoc}" var="d"
                                filterBy="#{d}" style="width:150px;font-size:12px"
                                dynamic="true" filterMatchMode="contains"
                                selectionMode="checkbox"
                                selection="#{myBean.selectedDataDoc}">
                    <p:ajax event="select" oncomplete="PF('myTable').filter()" />
                    <p:ajax event="unselect" oncomplete="PF('myTable').filter()" />
                    <p:treeNode>
                        <h:outputText value="#{d}" />
                    </p:treeNode>
                    <p:treeNode type="month">
                        <h:outputText value="#{d}" />
                    </p:treeNode>
                    <p:treeNode type="date">
                        <h:outputText value="#{d}">
                            <f:convertDateTime pattern="dd-MM-yyyy" timeZone="CET" />
                        </h:outputText>
                    </p:treeNode>
                </cf:treeFilter>
            </cf:overlayFilterPanel>
        </cf:filterOutputPanel>
    </f:facet>
    <h:outputText value="#{row.documentDate}" >
        <f:convertDateTime pattern="dd-MM-yyyy" timeZone="CET"/>
    </h:outputText>
</p:column>

FilterOutputPanel

@FacesComponent("view.components.FilterOutputPanel")
public class FilterOutputPanel extends OutputPanel implements ValueHolder{

    public FilterOutputPanel() {
        super();
    }

    /*
     * This methods returns the local value of his child UIComponent
     * that is a ValueHolder
     */
    @Override
    public Object getLocalValue() {
        for(UIComponent c : this.getChildren()) {
            if(c instanceof ValueHolder)
                return ((ValueHolder) c).getLocalValue();
        }
        return null;
    }

    ...

}

OverlayFilterPanel

@FacesComponent("view.components.OverlayFilterPanel")
public class OverlayFilterPanel extends OverlayPanel implements ValueHolder{

    public OverlayFilterPanel() {
        super();
    }

    /*
     * This method returns the local value of his child UIComponent,
     * assuming that the only child is a TreeFilter
     */
    @Override
    public Object getLocalValue() {
        return ((ValueHolder) this.getChildren().get(0)).getLocalValue();
    }

    ...

}

TreeFilter类

@FacesComponent("view.components.TreeFilter")
public class TreeFilter extends Tree implements ValueHolder{

    public TreeFilter() {
        super();
    }

    /*
     * This method explores the Tree and returns the data selected on the leaf nodes 
     */
    @Override
    public Object getLocalValue() {
        TreeNode[] selectedDataDoc = (TreeNode[]) this.getSelection();
        if(selectedDataDoc==null)
            return null;
        Date[] dateArray = new Date[selectedDataDoc.length];
        int j=0;
        for(int i=0; i<selectedDataDoc.length; i++) {
            TreeNode n = selectedDataDoc[i];
            if(n.isLeaf()) {
                dateArray[j] = (Date)n.getData();
                j++;
            }
        }
        Date[] result = new Date[j];
        for(int i=0; i<j; i++) {
            result[i]=dateArray[i];
        }
        return result;
    }

    ...

}

customtaglib.xml

...
 <tag>
  <tag-name>treeFilter</tag-name>
  <component>
   <description>Custom Tree filter</description>
   <component-type>view.components.TreeFilter</component-type>
   <renderer-type>org.primefaces.component.TreeRenderer</renderer-type>
  </component>
 </tag>
 <tag>
  <tag-name>overlayFilterPanel</tag-name>
  <component>
   <description>Custom Overlay Filter Panel</description>
   <component-type>view.components.OverlayFilterPanel</component-type>
   <renderer-type>org.primefaces.component.OverlayPanelRenderer</renderer-type>
  </component>
 </tag>
 <tag>
  <tag-name>filterOutputPanel</tag-name>
  <component>
   <description>Custom Output Panel for filters</description>
   <component-type>view.components.FilterOutputPanel</component-type>
   <renderer-type>org.primefaces.component.OutputPanelRenderer</renderer-type>
  </component>
 </tag>
...

web.xml

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/customtaglib.xml</param-value>
</context-param>