JSF 验证器和输出标签

JSF Validator and outputLabel

我正在使用采用以下技术的 Web 应用程序 spring 4.3 JSF 2.2.14 PrimeFaces 6.1 全脸 2.6.4

我需要验证 h:inputText,我正在尝试使用 javax.faces.validator.Validator 界面。

一切正常,但当验证失败时,我无法检索使用 "for" 属性存储在 p:outputLabel 中的字段标签。

Facelets 代码

<p:outputLabel id="selectedAdvPriceOutputLabel" for="selectedAdvPrice" value="#{msg['prezzo']}"/>

<h:inputText id="selectedAdvPrice" 
             value="#{addAdvertisingController.advertisingBean.price}" 
             class="form-control" 
             converter="javax.faces.BigDecimal" 
             required="#{empty param[draftSave.clientId] and empty param[draftSaveXS.clientId]}" 
             requiredMessage="#{msg['prezzo']} #{msg['campoObbligatorio']}">
  <f:validator binding="#{numberGreaterThanZeroJsfValidator}" />
</h:inputText>

验证器 - 验证方法

public void validate(FacesContext context, UIComponent component, Object value) {
        if (value != null) {
            String v = value.toString();
            if (StringUtils.isNotEmpty(v)) {
                try {
                    BigDecimal bd = new BigDecimal(v);
                    if(bd.compareTo(BigDecimal.ZERO) <= 0){
                        // how to retrieve the field label???
                        FacesMessage msg = new FacesMessage("messageWithout label", "messageWithout label");
                        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                        throw new ValidatorException(msg, new IllegalArgumentException(exceptionMessage));
                    }
                } catch (NumberFormatException e) {
                        FacesMessage msg = new FacesMessage("messageWithout label", "messageWithout label");
                        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                        throw new ValidatorException(msg, new IllegalArgumentException(exceptionMessage));
                }

            }
        }
    }

如何检索链接到未通过验证的 h:inputText 的 p:outputLabel 的值属性? 谢谢

根据Primefaces User's Guide --> 3.93 OutputLabel

Auto Label
OutputLabel sets its value as the label of the target component to be displayed in validation errors so the target component does not need to define the label attribute again.

<h:outputLabel for="input" value="Field" />
<p:inputText id="input" value="#{bean.text}" label="Field"/>

can be rewritten as;

<p:outputLabel for="input" value="Field" />
<p:inputText id="input" value="#{bean.text}" />

这意味着,OutputLabel 只是设置标签所附加的组件的 label 属性。

只需在验证器中检索此属性,例如以这种方式:

public void validate(FacesContext context, UIComponent component, Object value) {

    Object labelObj = component.getAttributes().get("label");
    String label = (labelObj!=null) ? labelObj.toString() : "Unknown label";
    .....
    .....
    // how to retrieve the field label???
    String message = String.format("%s : My conversion error message", label);
    FacesMessage msg = new FacesMessage(message,message) ;
    .....
    ..... 

我已经测试过了,它适用于 p:inputTexth:inputText 组件。


Hi, I've debugged the code and component.getAttributes().get("label") is null

我在 JSF 2.2/Primefaces 6.1/Wildfy 上再次测试了它 10.x 并且它有效。
这是 GitHub link 上的一个简单演示项目

index.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">

<h:head></h:head>
<h:body>
    <h:form>
        <p:panel id="panel" header="Form" style="margin-bottom:10px;">
            <p:messages id="messages" />

            <h:panelGrid columns="2" cellpadding="5">

                <p:outputLabel id="label1_id"
                    for="input1_id" value="This Is My label for h:input" />

                <h:inputText id="input1_id" value="#{myBean.price1}"
                    required="true" >
                    <f:validator validatorId="MyValidator" />
                </h:inputText>

                <p:outputLabel id="label2_id"
                    for="input2_id" value="This Is My label for p:input" />

                <p:inputText id="input2_id" value="#{myBean.price2}" required="true">
                    <f:validator validatorId="MyValidator" />
                </p:inputText>

            </h:panelGrid>
            <p:commandButton update="panel" value="Submit" />

        </p:panel>
    </h:form>
</h:body>
</html>

豆子

@Named
@SessionScoped
public class MyBean implements Serializable {

    private static final long serialVersionUID = 5455916691447931918L;

    private Integer price1;

    private Integer price2;

    public Integer getPrice2() {
        return price2;
    }

    public void setPrice2(Integer price2) {
        this.price2 = price2;
    }

    public Integer getPrice1() {
        return price1;
    }

    public void setPrice1(Integer price1) {
        this.price1 = price1;
    }
}

验证器

@FacesValidator("MyValidator")
public class MyValidator implements Validator {

    public void validate(FacesContext context, UIComponent component, Object value) {

        Object labelObj = component.getAttributes().get("label");
        String label = (labelObj!=null) ? labelObj.toString() : "Unknown label";

        if (value != null) {
            String v = value.toString();
            if (null != v && !v.isEmpty()) {
                try {
                    BigDecimal bd = new BigDecimal(v);
                    if (bd.compareTo(BigDecimal.ZERO) <= 0) {
                        // how to retrieve the field label???
                        String message = String.format("%s : Value must be greater than 0", label);
                        FacesMessage msg = new FacesMessage(message,message) ;
                        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                        throw new ValidatorException(msg, new IllegalArgumentException("Validator exception:" + message));
                    }
                } catch (NumberFormatException e) {
                    String message = String.format("%s : Value must be a number", label);
                    FacesMessage msg = new FacesMessage(message,message);
                    msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                    throw new ValidatorException(msg, new IllegalArgumentException("Validator exception:" + message));
                }
            }
        }
    }

}

结果是:

一些可能有帮助或很常见的事情:

  • *:outputLabel 中删除 id,因为不需要
  • 如果您的验证器抛出 javax.faces.validator.ValidatorException,请使用 validatorMessage="#{bundle.SOME_FIELD_VALIDATION_ERROR}" 获得可本地化的消息(当然,您可以在验证器 class 上方导入它)
  • 摆脱标签检索的代码,见上面validatorMessage字段
  • <f:validator binding="#{someValidator}" />好像问题比较多,一般的做法是:<f:validator validatorId="SomeFooValidator" />*:inputText之内(你得让它不自闭)
  • 然后用 @FacesValidator ("SomeFooValidator") (javax.faces.validator.FacesValidator)
  • 注释你的验证器 class

您使用的是 JSF2.2 吗?