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

Validation for xp:inputtext freezes my Xpage, why?

在 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 中的事件不再被触发。

我怎样才能使这个想法奏效? (通过checkbox inputtext控件显示,使其成为必填项,通过checkbox再次隐藏并使其成为非必填项)

首先让我们说您对 JSF 生命周期中发生的事情和时间感到困惑。 使用以下事件处理程序,没有任何 execMode="partial":

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

您是在告诉服务器“重新执行”整个页面(这不是一个好的做法,您没有有效地判断服务器实际上可以跳过页面的哪些部分,因为它们不会发挥任何积极作用,这是一个典型的例子),包括 xp:inputText required="true"。验证阶段失败,因为输入为空 - 它不知道您不再需要它 - 因此跳过任何其他后续阶段,包括再次隐藏输入。

您可以通过在事件处理程序中添加 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" 打扰)。