Как проверить максимальное количество проверенных значений selectManyCheckbox на основе текущего выбора selectOneMenu? - PullRequest
4 голосов
/ 26 июля 2011

Я использую 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>

(примечание: я неуверен, что <p:ajax event> правильный)

Боб:

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.
            }
        }
    }
}

После попытки решения 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)

Обновление

Спасибо, проблема решена :)

1 Ответ

4 голосов
/ 26 июля 2011

Вам нужен пользовательский Validator, который выбрасывает ValidatorException, когда флажок содержит слишком много отмеченных элементов. Этот Validator должен быть присоединен к компоненту флажка, и где-то в представлении должен быть компонент <h:message> или <h:messages>, который может отображать ошибку проверки.

Событие ajax неверно. Внутри выпадающего списка вы бы хотели подключить событие change. Внутри флажка или переключателя вы хотели бы вместо этого подключить событие click. И то, и другое уже установлено по умолчанию, если оставить атрибут event по умолчанию. Каждый компонент, в свою очередь, должен ajax-представить себя и другого и, наконец, повторно обработать компонент сообщения, чтобы отразить ошибку проверки.

Чтобы отобразить выбранное раскрывающееся значение в пользовательском валидаторе, самым чистым способом было бы установить весь раскрывающийся компонент в качестве настраиваемого атрибута компонента-флажка. Этого можно достичь, привязав раскрывающийся список к представлению с помощью атрибута binding и указав его в качестве значения <f:attribute> внутри флажка. Компонент раскрывающегося списка и, следовательно, также его значение могут быть получены внутри пользовательского валидатора.

Подводя итог, приведенный ниже пример запуска должен работать (обратите внимание, что я использовал <f:ajax>, поскольку <p:ajax> не добавляет никаких дополнительных преимуществ в данном конкретном случае, и я по общему признанию не могу сказать из головы, как и если это будет работать):

<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<String>. Если это на самом деле a String[], то вам необходимо соответствующим образом изменить код валидатора.

...