如何让 h:inputText 的必需属性依赖于 h:selectOneMenu 中的某些值集?

Posted

技术标签:

【中文标题】如何让 h:inputText 的必需属性依赖于 h:selectOneMenu 中的某些值集?【英文标题】:How to let the required attribute of h:inputText depend on certain set of values from 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')" />

在上面的代码中,#selectedPaymentTypeh:selectOneMenu binding 中定义。

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

【问题讨论】:

【参考方案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;)。此外,您的验证器示例绝对不是“客户端解决方案”。这个答案在所有领域都是错误的。

以上是关于如何让 h:inputText 的必需属性依赖于 h:selectOneMenu 中的某些值集?的主要内容,如果未能解决你的问题,请参考以下文章

JSONSchema - 依赖于父属性的必需属性

如何在 JSF 中构建“编辑”按钮并在 h:outputText 和 h:inputText 之间切换

绑定到 Integer 属性的 h:inputText 正在提交值 0 而不是 null

如何在 h:inputTextarea 上设置 maxlength 属性

如何在 jsf 中动态添加 h:inputText 而不会丢失之前动态添加的 h:inputText 值? [复制]

如何在 h:inputText 中保留以前输入的数据?