对xp:inputtext的验证冻结了我的Xpage,为什么?

时间:2018-09-20 11:09:12

标签: xpages

在Xpage上,我有一个xp:inputtext控件的show / hide函数。当显示输入框时,我希望它是必需的。

这是我的代码:

<xp:panel 
    styleClass="row" 
    id="pnlInterest">       
    <div class="col-sm-12">
        <table>
            <tr>                
                <td>
                    <xp:checkBox id="cbInterest" value="#{eventBean.event.interest}">                       
                        <xp:eventHandler event="onclick"
                            submit="true" refreshMode="partial"
                            refreshId="pnlInterest">
                            <xp:this.action><![CDATA[#{javascript:print("click")
print("selected " + eventBean.getEvent().getInterest())
if(eventBean.getEvent().getInterest() != "true"){

eventBean.getEvent().setYourName("");
}}]]></xp:this.action>
                        </xp:eventHandler></xp:checkBox>
                </td>
                <td>
                    <label class="checkbox">
                        <span>Are you interested in this event?
                    </label>
                </td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <xp:panel>
                        <xp:this.rendered><![CDATA[#{javascript:if ("true" == eventBean.getEvent().getInterest()){
return true;
} else{
return false;
}}]]></xp:this.rendered>
                        <div class="form-inline">
                            <div class="form-group">
                                <xp:inputText
                                    id="inpYourName"
                                    value="#{eventBean.event.yourName}" required="true">
                                    <xp:this.attrs>
                                        <xp:attr
                                            name="placeholder" value="Enter your name" />
                                    </xp:this.attrs>
                                    <xp:this.validators>
                                        <xp:validateRequired
                                            message="You forgot to enter your name">
                                        </xp:validateRequired>
                                    </xp:this.validators></xp:inputText>
                                <xp:message id="msg"
                                    for="inpYourName">
                                </xp:message>
                            </div>
                        </div>
                    </xp:panel>
                </td>
            </tr>
        </table>
    </div>          
</xp:panel> 

当我没有为xp:inputtext设置验证时,显示/隐藏效果很好。但是,一旦添加它并通过复选框显示它,便无法将其隐藏起来。 onclick中的事件不再被触发。

如何使这个想法可行? (通过复选框inputtext控件显示,使其为必选,通过复选框再次隐藏,并使其非必选)

1 个答案:

答案 0 :(得分:3)

让我们开始说,您对JSF生命周期以及何时发生的事情感到惊讶。 使用以下事件处理程序,不带任何execMode="partial"

<xp:eventHandler event="onclick"
                        submit="true" refreshMode="partial"
                        refreshId="pnlInterest">

您正在告诉服务器“重新执行”整个页面(这不是一个好习惯,因为服务器实际上没有跳过,因此您实际上无法有效地跳过服务器的页面哪些部分)有效部分(这是一个典型示例),其中包含xp:inputText required="true"。验证阶段失败是因为输入为空-它不知道您不再需要输入-因此跳过了其他后续阶段,包括再次隐藏输入。

您可以通过在eventHandler中添加disableValidators="true"属性来修复它。基本上,这指示服务器跳过验证阶段,该阶段将为您提供预期的结果。实际上,我很少使用此选项,因为您只是通过缩小执行范围来解决它。例如,我将重构代码以使其更高效,同时也遵循标准(实际上,清除复选框时,您也在清除输入,在这种情况下,最好使用valueChangeListener)。它可以遵循以下原则:

豆子

public class Controller implements Serializable {

    private static final long serialVersionUID = 1L;

    private String interest;
    private String yourName;

    public String getInterest() {
        return interest;
    }

    public String getYourName() {
        return yourName;
    }

    public boolean isInterested() {
        return interest != null && Boolean.valueOf(interest);
    }

    public void setInterest(String interest) {
        this.interest = interest;
    }

    public void setYourName(String yourName) {
        this.yourName = yourName;
    }

    public void onInterestChange(ValueChangeEvent event) throws AbortProcessingException {
        if ("true".equals(event.getNewValue())) {
            setYourName(null);
        }
    }

}

onInterestChange设置为不同于布尔值interest的任何时候,true都会清除输入名称值。 isInterested方法在xsp上提供了方便和简洁,但是如果您创建布尔型转换器,则可以避免所有这些麻烦。

页面

<table>
    <tr>
        <td>
            <xp:checkBox id="cbInterest" value="#{controller.interest}"
                checkedValue="true" uncheckedValue="false" valueChangeListener="#{controller.onInterestChange}">
                <xp:eventHandler event="onchange" submit="true" execMode="partial" refreshMode="partial"
                    refreshId="rowName" />
            </xp:checkBox>
        </td>
        <td>
            <label class="checkbox">
                <span>Are you interested in this event?</span>
            </label>
        </td>
    </tr>
    <xp:tr id="rowName">
        <td />
        <td>
            <xp:div styleClass="form-inline" rendered="#{controller.interested}">
                <div class="form-group">
                    <xp:inputText id="inpYourName" value="#{controller.yourName}"
                        required="true">
                        <xp:this.attrs>
                            <xp:attr name="placeholder" value="Enter your name" />
                        </xp:this.attrs>
                        <xp:this.validators>
                            <xp:validateRequired message="You forgot to enter your name" />
                        </xp:this.validators>
                    </xp:inputText>

                    <xp:message id="msg" for="inpYourName" />
                </div>
            </xp:div>
        </td>
    </xp:tr>
</table>

<xp:button value="Submit" id="button1">
    <xp:eventHandler event="onclick" submit="true"
        refreshMode="complete" />
</xp:button>

如您所见,我没有在复选框组件中使用disableValidators="true"。那是因为我将执行范围缩小到了复选框本身。实际上,提交表单后,服务器将仅在复选框上执行,因此将忽略视图根目录上的所有其他内容(这意味着xp:inputText required="true"不会受到干扰)。