【问题标题】:How to validate the maximum amount of checked values of a selectManyCheckbox based on the current selection of a selectOneMenu?如何根据 selectOneMenu 的当前选择验证 selectManyCheckbox 的最大检查值数量?
【发布时间】:2011-10-13 05:59:10
【问题描述】:

我正在使用 JSF 2.0 和 PrimeFaces。我有一个 selectOneMenu 和一个 selectManyCheckbox。我想实现这个场景:

当用户选择时:

  • option1(PieChart),则允许用户最多勾选一个复选框
  • option2(BarChart),则允许用户最多勾选两个复选框

这是我目前的尝试,观点:

<h:selectOneMenu value="#{bean.chartType}">
    <f:selectItem itemValue="PieChart" itemLabel="PieChart" />
    <f:selectItem itemValue="BarChart" itemLabel="BarChart" />
    <p:ajax event="keyup" update="checkbox" listener="#{bean.checkboxHandler}" />
</h:selectOneMenu>

<h:selectManyCheckbox id="checkbox" value="#{bean.selectedItemscheckbox}">
    <f:selectItem itemValue="priority" itemLabel="By priority" />
    <f:selectItem itemValue="project" itemLabel="By project" />
    <f:selectItem itemValue="issuetype" itemLabel="By IssueType" />
    <f:selectItem itemValue="group" itemLabel="By group" />
</h:selectManyCheckbox>

(注意:我不确定&lt;p:ajax event&gt; 是否正确)

豆子:

public void checkboxHandler() {
    Iterator it1 = selectedItemscheckbox.iterator();
    if (chartType.equals("PieChart")) {
        while (it1.hasNext()) {
            if (selectedItemscheckbox.size() > 1) {
                // Here should be somthing that shows a message to the user.
            }
        }
    }
}

在tring BalusC的解决方案后,出现了这个错误:

java.lang.InstantiationException: DAOKPI.TestAjax$MyCheckboxValidator
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at com.sun.faces.application.ApplicationImpl.newThing(ApplicationImpl.java:1699)
at com.sun.faces.application.ApplicationImpl.createValidator(ApplicationImpl.java:1557)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.createValidator(ValidatorTag     HandlerDelegateImpl.java:238)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.applyAttachedObject(Validato    rTagHandlerDelegateImpl.java:132)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.applyNested(ValidatorTagHand    lerDelegateImpl.java:205)
at com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl.apply(ValidatorTagHandlerDel    egateImpl.java:87)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandle     r.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDel    egateImpl.java:188)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:188)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:188)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:188)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:137)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:188)
at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:120)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:93)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:86)
at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:152)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:769)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:100)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:410)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1534)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:662)

更新

谢谢你的问题解决了:)

【问题讨论】:

    标签: java validation jsf-2 primefaces


    【解决方案1】:

    您需要一个自定义的Validator,当复选框包含太多选中的项目时,它会抛出一个ValidatorException。这个Validator 需要附加到复选框组件,并且应该在视图中的某处可以显示验证错误的&lt;h:message&gt;&lt;h:messages&gt; 组件。

    ajax 事件错误。在下拉列表中,您想挂接change 事件。在复选框或单选按钮内,您想挂上click 事件。当您将 event 属性保留为默认值时,这两者已经是默认值。每个组件应该依次提交自己和另一个组件,最后重新渲染消息组件以反映验证错误。

    为了在自定义验证器中计算选定的下拉值,最简洁的方法是将整个下拉组件设置为复选框组件的自定义属性。这可以通过binding 属性将下拉列表绑定到视图并在复选框内指定为&lt;f:attribute&gt; 的值来实现。然后可以在自定义验证器中获取下拉组件及其值。

    总之,下面的启动示例应该可以工作(请注意,我使用 &lt;f:ajax&gt; 作为 &lt;p:ajax&gt; 在这种特殊情况下没有增加任何额外的优势,我承认我无法从头顶告诉我如何以及是否会起作用):

    <h:selectOneMenu id="chartType" binding="#{chartType}" value="#{bean.chartType}">
        <f:selectItem itemValue="PieChart" itemLabel="PieChart" />
        <f:selectItem itemValue="BarChart" itemLabel="BarChart" />
        <f:ajax execute="chartType checkbox" render="checkboxmessage" />
    </h:selectOneMenu>
    <h:selectManyCheckbox id="checkbox" value="#{bean.selectedItemscheckbox}">
        <f:selectItem itemValue="priority" itemLabel="By priority" />
        <f:selectItem itemValue="project" itemLabel="By project" />
        <f:selectItem itemValue="issuetype" itemLabel="By IssueType" />
        <f:selectItem itemValue="group" itemLabel="By group" />
        <f:validator validatorId="myCheckboxValidator" />
        <f:attribute name="chartType" value="#{chartType}" />
        <f:ajax execute="chartType checkbox" render="checkboxmessage" />
    </h:selectManyCheckbox>
    <h:message id="checkboxmessage" for="checkbox" />
    

    @FacesValidator("myCheckboxValidator")
    public class MyCheckboxValidator implements Validator {
    
        @Override
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
            UIInput chartTypeComponent = (UIInput) component.getAttributes().get("chartType");
            String chartType = (String) chartTypeComponent.getValue();
            List<String> selectedItemscheckbox = (List<String>) value;
    
            if ("PieChart".equals(chartType) && selectedItemscheckbox.size() > 1) {
                throw new ValidatorException(new FacesMessage("Max 1 item allowed"));
            }
            else if ("BarChart".equals(chartType) && selectedItemscheckbox.size() > 2) {
                throw new ValidatorException(new FacesMessage("Max 2 items allowed"));
            }
        }
    
    }
    

    请注意,我假设 #{bean.selectedItemscheckbox}List&lt;String&gt;。如果它实际上String[],那么您需要相应地更改验证器代码。

    【讨论】:

    • ,感谢您的回复,我已经尝试过您的建议但出现错误,我已更新我的帖子,出现错误
    • 您不应将验证器创建为嵌套类。您是否了解何时可以创建或不可以创建嵌套类?
    猜你喜欢
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 2019-02-09
    • 2017-07-09
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 2021-09-12
    相关资源
    最近更新 更多