【问题标题】:How to let the required attribute of h:inputText depend on certain set of values from h:selectOneMenu?如何让 h:inputText 的必需属性依赖于 h:selectOneMenu 中的某些值集?
【发布时间】:2012-11-10 02:44:54
【问题描述】:

我正在使用 JSF 2.0。

我的页面上有一个h:selectOneMenu,其中包含一个值列表,并且同一页面上有一个h:inputText,其required 应取决于h:selectOneMenu 的当前选定值。只有特定的一组值应该触发required 检查,其他的则不会。

这是我尝试过的:

<h:inputText ... required="#{(selectedPaymentType.value == 'some value') || (selectedPaymentType.value == 'other value')}" />

在上面的代码中,#{selectedPaymentType}h:selectOneMenu binding 中定义。

还有 3 个像这样的值应该触发 required 属性到 true。这看起来有点笨拙。有更好的方法吗?

【问题讨论】:

    标签: java validation jsf jsf-2


    【解决方案1】:

    Fant 给出了正确方向的提示,即您应该使用具有 required 属性的枚举,但您似乎并不完全确定如何正确实现它。诚然,范特的回答不够详尽。所以这里有一个更详细的答案。

    基本上,您需要将所有下拉列表值替换为如下所示的枚举:

    public enum PaymentType {
        FOO("Some label for foo", true),
        BAR("Some label for bar", false),
        BAZ("Some label for baz", true);
    
        private String label;
        private boolean required;
    
        private PaymentType(String label, boolean required) {
            this.label = label; 
            this.required = required;
        }
    
        public String getLabel() { 
            return label;
        }
    
        public boolean isRequired() {
            return required;
        }
    }
    

    并按如下方式使用

    <h:selectOneMenu binding="#{selectedPaymentType}" value="#{bean.selectedPaymentType}">
        <f:selectItems value="#{bean.availablePaymentTypes}" var="paymentType"
            itemValue="#{paymentType}" itemLabel="#{paymentType.label}" />
    </h:selectOneMenu>
    <h:inputText ... required="#{selectedPaymentType.value.required}" />
    

    private PaymentType selectedPaymentType; // +getter+setter
    
    public PaymentType[] getAvailablePaymentTypes() { 
        return PaymentType.values();
    }
    

    (或者如果您使用的是 OmniFaces,请使用 &lt;o:importConstants&gt;,那么对于 &lt;f:selectItems&gt;,您不需要这样的吸气剂;不,无论如何您都不需要转换器,JSF/ EL 已经内置了枚举转换)

    看,required 属性现在已经简化了很多,因为它已经在与所选值关联的模型中定义了。

    【讨论】:

    • 谢谢。现在我明白了如何用枚举来实现它。但我不能这样做,它是一个列表。那么函数isRequired() 在这种情况下我最好的选择?
    • 我不明白这究竟是如何形成问题的。 “它的列表”是什么意思?字符串列表?从哪里?数据库?您的具体问题不是您不确定如何将枚举用作数据库值吗?
    • 抱歉,这不是一个列表。我将它与用于填充 selectOneMenu 的列表混淆了。是的,我可以将其更改为枚举。我确实知道有关 ising 枚举的基础知识。我想我现在就可以了。谢谢你:-)
    【解决方案2】:

    如果在您的设计中可能,您可以使用枚举作为您的 PaymentType,其中包括一些类似的接口

    public interface RequireSomeMoreStuff {
       public boolean required();
    }
    
    public enum PaymentType implements RequireSomeMoreStuff {
       FOO { boolean required() { return true; } },
       BAR { boolean required() { return false; } }
    }
    

    【讨论】:

    • 感谢您的快速回复。但即使我这样做了……那不是服务器端验证吗?我正在寻找客户端的东西。
    • 是的,因为您的解决方案已经如此。但是现在 JSF 中的代码将更短且可读性更好。如果您添加或删除一些 PaymentTypes,您不必更改 jsf 中的某事。我以为那是你要找的地方。 --- 如果你想要一些客户端验证,你必须使用一些 JavaScript 或类似的东西。但我认为(仅)在客户端进行验证并不是一个好主意,因为您总是可以绕过客户端验证。
    • 请参阅 here 了解我想要实现的目标。 selectedPaymentTypeselectOneMenu 上的绑定,而不是 bean 属性。所以我想这应该是客户端。虽然不确定
    【解决方案3】:

    只有在您的selectOneMenu 的某些值被选中时,我才会使用a4j 来呈现inputText:

    <h:selectOneMenu value="#{MyBean.selectedValue}">
        <f:selectItems value="#{MyBean.listOfValues}" />
        <a4j:support event="onchange" reRender="requiredText" ajaxSingle="true"/>
    </h:selectOneMenu>
    
    <a4j:outputPanel id="requiredText">
        <h:inputText value="#{MyBean.inputValue}" rendered="#{(MyBean.selectedValue == value_1) || (MyBean.selectedValue == value_2) || ...}" />
    </a4j:outputPanel>
    

    为了避免 inputText 的 rendered 参数上出现大字符串,我建议您创建一个执行这些条件的布尔函数:rendered="#{MyBean.inputTextIsRendered}

    客户端解决方案

    还有一个基于验证器的解决方案。这是我的方法:

    • JSF 代码

    上面的selectOneMenu 代码使用binding 标记将selectOneMenu 中选择的值与将在验证器方法中检索到的属性绑定,该属性为inputText 组件声明。

    • 验证器类

    然后,您需要创建CheckInputValue 验证器类。

    public class CheckInputValue implements Validator {
        public CheckInputValue() {}
    
        public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
    
            //We retrieve thei binded value:
            UIInput confirmComponent = (UIInput) component.getAttributes().get("selectedValue");
            String theValue = confirmComponent.getSubmittedValue();
    
            //Here you check the retrieved value with the list of values that makes your inputText required.
            //In these cases you will chech the inputText is not empty and, if so, you return a ValidatorException:
            if(isEmpty){
                FacesMessage message = new FacesMessage();
                message.setDetail("inputText cannot be empty");
                message.setSummary("inputText cannot be empty");
                message.setSeverity(FacesMessage.SEVERITY_ERROR);
                throw new ValidatorException(message);
            }
        }
    }
    
    • faces-config.xml

    最后,您必须在faces-config.xml 中声明您的验证器类:

    <validator>
        <validator-id>CheckInputValue</validator-id>
        <validator-class>myPackage.myValidations.CheckInputValue</validator-class>
    </validator>
    

    【讨论】:

    • Ajax4jsf 的答案没有意义。你没有理解具体的问题。 OP 的代码有效,但他发现required 属性中的EL 表达式非常笨拙。此外,用过时的 JSF 1.x 特定方法回答 JSF 2.x 问题是没有意义的(您可以只使用 JSF 2.x 自己的&lt;f:ajax&gt;)。此外,您的验证器示例绝对不是“客户端解决方案”。这个答案在所有领域都是错误的。
    猜你喜欢
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 2020-10-19
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    相关资源
    最近更新 更多