JSF中的异步验证器

gab*_*bga 5 javascript jsf jsf-2

我有一个包含编辑框和按钮的简单表单:

<h:form id="addForm">
    <h:outputLabel value="Add item here" /><br />
    <p><h:inputText id="itemInput" value="#{myController.itemToAdd}" validator="myValidator" />
    <h:message for="itemInput" /></p>
    <h:commandButton value="Add" action="#{myController.addItemToList}">
        <f:ajax execute="@form" render="@form :addedItems" />
    </h:commandButton>
</h:form>
Run Code Online (Sandbox Code Playgroud)

当用户单击该按钮时,将完成一些基本验证,如果一切正常,则将该项添加到数据表中:

<h:panelGrid id="addedItems">
    <h:dataTable value="#{myController.itemMap.entrySet()}" var="itemMapEntry" >
        <h:column>
            <f:facet name="header">
                <h:outputText value="Items" />
            </f:facet>
            <h:commandButton value="Remove/Modify" action="#{myController.removeItemFromList(itemMapEntry.getKey())}">
                <f:ajax render=":addedItems :addForm" />
            </h:commandButton>
            <h:outputText value="#{itemMapEntry.getKey()}" />
        </h:column>
        <h:column>
            <f:facet name="action">
                <h:outputText value="" />
            </f:facet>
            <h:outputText value="#{itemMapEntry.getValue().toString()}" id="itemValidationStatus" />
        </h:column>
    </h:dataTable>
</h:panelGrid>
Run Code Online (Sandbox Code Playgroud)

现在,我想要实现的是当用户输入项目时,第一次,初步,验证完成,如果验证成功,则将项目添加到表格中,其中列表与验证状态一起显示(例如,验证,无效,有效).当项目被添加到表中时,另一个更耗时的验证开始,并且当验证完成时,表中的itemValidationStatus被更新.我不想在耗时的验证过程中阻止用户.相反,我想允许用户在已经添加的项目被验证时添加更多项目.

我看到三种解决方法:

  1. 要注册某个将在对象上作出反应的JS观察者正在托管bean中进行更新

  2. 要从托管bean触发渲染,这样就可以生成一个验证线程,在完成后会触发渲染

  3. 有一些方法可以通过JS异步启动验证并注册一个回调函数,该函数将触发渲染或直接更新值

问题是我在网上找不到任何可以指向正确方向的东西.我试图用普通的JSF(没有Prime Faces或类似的工具)来解决这个问题.

编辑:

我被建议另一个问题作为可能的重复(JSF,定期刷新一个带有ajax的组件?).我不是在寻找一个可以周期性地进行轮询的解决方案,而是在基础数据发生变化时进行更新.它只会改变一次,所以明显的解决方案是事件监听器或类似的.当然,这也可以通过定期民意调查来解决,但这似乎是我所追求的非常低的水平.

gab*_*bga 1

现在我通过以下更改解决了这个问题(受到此 JQuery 相关问题How to trigger JSF render from jQuery 的启发):

  1. onevent="validateItemList"<f:ajax>表单的标签中添加了:

    <h:form id="addForm">
        <h:outputLabel value="Add item here" /><br />
        <p><h:inputText id="itemInput" value="#{myController.itemToAdd}" validator="myValidator" />
        <h:message for="itemInput" /></p>
        <h:commandButton value="Add" action="#{myController.addItemToList}">
            <f:ajax execute="@form" onevent="validateItemList" render="@form :addedItems" />
        </h:commandButton>
    </h:form>
    
    Run Code Online (Sandbox Code Playgroud)
  2. 我添加了一个带有隐藏按钮的隐藏表单,该按钮触发耗时的验证并重新呈现表格:

    <h:form id="hiddenForm">
        <h:commandButton value="" action="#{myController.validateItemMap}" id="validatorButton" style="display:none">
            <f:ajax execute="@form" render=":addedItems" />
        </h:commandButton>
    </h:form>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我添加了一个回调 JS 函数来“按下”隐藏按钮:

    <script type="text/javascript">
        function validateItemList(data){
            if(data.status == "success"){
                document.getElementById("hiddenForm:validatorButton").click();
            }
        }
    </script>
    
    Run Code Online (Sandbox Code Playgroud)