1

我使用 Prime faces 3.4.1 作为组件框架和 JSF 2.0 作为服务器端框架

以下是我的要求

1)我有一个标签为“需要开会”的字段。然后我有 SelectOneRadio 有两个选项“否”和“是”,默认值为“否”。我正在使用 JSF/HTML 组件 h:SelectOneRadio。

2)我有另一个字段是日历组件,这是一个 primefaces 日历组件。当用户选择表示“需要会议”的“是”时,用户应该从日历控件中选择一个日期。

3) 如果用户选择“是”并且没有选择日期,则应显示验证消息,指示应选择日期。

我创建了一个自定义验证组件并附加到 SelectOneRadio,我可以在自定义验证器中看到选定的值。现在,我尝试从 Calendar 组件中获取值以检查该值是否为空,通过 UIComponent.getParent().findCompoent("rvmDate"),我得到了组件但我不知道如何检查日期组件为空或包含任何值。

请帮我获取用户选择的日期值。

请帮我解决问题。或者还有其他方法吗?请找到源代码。

XHTML 页面

<h:selectOneRadio id="rvmMeetingOption"
    readonly="#{wipMB.rvmMeetingOptionReadOnly}"
    value="#{wipMB.requirementsMeeting}" 
    disabled="#{wipMB.rvmMeetingOptionDisabled}"
    validator="#{wipMB.validateRVMDate}"
    validatorMessage="Please enter RVM Date>

     <f:selectItem itemLabel="No" itemValue="0"></f:selectItem>
     <f:selectItem itemLabel="Yes" itemValue="1" ></f:selectItem>
     <f:attribute value="#{rvmDateComp}" name="rvmDateComp"></f:attribute>
</h:selectOneRadio>

<p:calendar id="rvmDate" 
        readonly="#{wipMB.rvmMeetingDateReadOnly}"
        disabled="#{wipMB.rvmMeetingDateDisabled}"
        readonlyInput="true"
        navigator="true" mode="popup" 
        pattern="dd/MM/yyyy" 
        value="#{wipMB.rvmDate}" 
        effect="explode" 
        yearRange="1900:2500" 
        style="margin-left:5px"
        binding="#{rvmDateComp}"
</p:calendar>
<p:message id="rvmDateMsg" for="rvmDate" display="both" ></p:message>

自定义验证器

public void validateRVMDate(FacesContext context, UIComponent component, Object value)
        throws ValidatorException
{
    String invalidDate;
    String rvmOption;
    Date rvmDate;
    String rvmDt = "";

    try
    {

        FacesContext fc = FacesContext.getCurrentInstance();

        rvmOption = value.toString();
        DateFormat formatter = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");


        UIInput rvmCompDt = (UIInput)component.getAttributes().get("rvmDateComp");

        rvmDateId = rvmCompDt.getId();
        rvmDt = rvmCompDt.getSubmittedValue() == null ? "" : rvmCompDt.getSubmittedValue().toString();


        if (rvmOption.equals("1") && rvmDt.isEmpty())
        {

            FacesMessage msg = new FacesMessage("RVM date is required");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            fc.addMessage("rvmDateMsg", msg);
            throw new ValidatorException(msg);

        }
    }

    catch (Exception ex)
    {
        String msg = ex.getMessage();
    }
}
4

3 回答 3

3

您首先需要immediate="true"从中删除<p:calendar>,否则在处理单选按钮时根本不会处理它。

然后,要检查字符串是否为空或空,只需执行

String dt = (String) uiCalendar.getSubmittedValue();

if (dt == null || dt.isEmpty()) {
    // dt is null or empty. Throw validator exception depending on the 
    // current radio button value. Note: you should not catch it yourself!
}

请注意,这与 JSF 无关。这只是基本的Java。您最初的尝试if (dt == "")确实是完全无效的。是一个对象,而String不是一个原始的。比较==对象是通过引用,而不是通过它们的内部值。从技术上讲,您应该使用它if (dt.equals("")),但isEmpty()更好。


与具体问题无关,更简单的方法是检查required日历组件属性中的单选按钮值。首先将单选按钮组件通过绑定到视图中的变量,然后在属性中binding引用其UIInput#getValue()方法。required

<h:selectOneRadio id="rvmMeetingOption" binding="#{rvmMeetingOption}"
        readonly="#{wipMB.rvmMeetingOptionReadOnly}"
        value="#{wipMB.requirementsMeeting}" 
        disabled="#{wipMB.rvmMeetingOptionDisabled}">
    <f:selectItem itemLabel="No" itemValue="0"></f:selectItem>
    <f:selectItem itemLabel="Yes" itemValue="1" ></f:selectItem>
</h:selectOneRadio>

<p:calendar id="rvmDate" 
        readonly="#{wipMB.rvmMeetingDateReadOnly}"
        disabled="#{wipMB.rvmMeetingDateDisabled}"
        readonlyInput="true"
        navigator="true" mode="popup" 
        pattern="dd/MM/yyyy" 
        value="#{wipMB.rvmDate}" 
        effect="explode" 
        yearRange="1900:2500" 
        style="margin-left:5px"
        required="#{rvmMeetingOption.value == 1}">
</p:calendar>
于 2013-02-08T11:35:05.197 回答
3

在 JSF 中,每个组件都是自己的一个小 MVC 堆栈;有模型(存储为值)、控制器(组件对象)和视图(渲染器)。验证器和控制器是架构的一部分,需要在模型和视图之间移动值。

虽然 JSF 验证器发挥着重要作用,但它只在这个小的 MVC 堆栈内部很重要。它们不是为了“验证表单”而设计的,它们是为了“验证组件价值”而设计的。可悲的是,“验证器”这个名字让每个来到 JSF 的人都认为,每次需要进行任何验证时,验证器就是解决方案。奇怪的是,转换器并没有被滥用。

在您的情况下,构建自定义验证器会产生一种奇怪的情况,其中:

  • 验证器和视图相互之间具有循环依赖关系,
  • 需要使用 hack(例如“立即”)和低级 API,
  • 在不太可能的地方硬编码视图逻辑,
  • 需要更多的知识并且是片状的。例如,根据单选按钮在文档顺序中是在日历之前还是之后,从日历获取值的逻辑可能会有所不同。

上面的问题是可以解决的,但是由于都是滥用JSF架构造成的,我觉得还是重新思考问题比较好。由于您的验证涉及应用程序流程,因此它非常适合 action 方法,其中所有复杂性都将分解为带有条件“addMessage”的单个简单“if”语句。

于 2013-02-08T10:16:12.403 回答
0

利用

UIInput uiCalendar = (UIInput) component.getParent().findComponent("rvmDate");
Date test = uiCalendar.getValue();
if(test==null){
throw ValidatorException
}

然后 test 将填写日期,或者在日期字段中未选择任何内容时为 null

于 2013-02-08T08:43:03.557 回答