仅在验证成功时渲染组件

Posted

技术标签:

【中文标题】仅在验证成功时渲染组件【英文标题】:Render a component only when validation success 【发布时间】:2015-12-03 16:10:30 【问题描述】:

在 JSF 2.X 中,是否可以仅在验证成功时才渲染组件?

在我的申请中,我有许多必须填写的字段。这些数据可以通过搜索键从 WebService 导入。

当用户输入有效的搜索键时,系统会搜索其他字段并使用新值呈现它们。但是当用户输入不存在的键(或任何其他验证错误)时,服务器会生成验证错误,但仍会呈现字段,从而丢失已填充的所有数据。

我需要的是用户可以执行查询,并且如果查询没有返回结果,这不会影响他已经输入的任何数据。

下面是一个代码示例。因此,如果用户填写了 updateThisOnSuccess 中的字段,并且在尝试查询但未成功后,填写的值不会丢失。

    <h:inputText value="#controller.searchWebService" >
        <f:ajax execute="@this" render="updateThisOnSuccess messages" />
    </h:inputText>

    <h:panelGroup id="updateThisOnSuccess">
        <h:inputText value="#controller.field" />
        <!-- other fields -->
    </h:panelGroup>

提交字段值以运行搜索似乎也不是一个选项,因为这将导致需要验证 updateThisOnSuccess 中的字段。


注意:我看到@BalusC 给the answer 提供了一个类似的问题,但这与我想知道的不同,为什么在这种情况下,总是呈现 foo-holder 并且 foo 是条件反射。这不是我的情况,因为这种方法会使控件在验证失败时不会出现。

【问题讨论】:

你的问题有点啰嗦,但我猜你基本上想要rendered="#not empty controller.searchWebService"?毕竟,这只是在rendered 属性中准确指定所需条件的问题。 打扰一下。我试过了,但英语不是我的母语。我需要的不是那个。如果 controller.searchWebService 上的验证失败,我需要维护 panelGroup updateThisOnSuccess 中 input[text]、select 等中输入的值。 如果验证通过,则必须使用新值重新呈现它们。换句话说,就好像 Ajax 是这样的: Validation OK &lt;f:ajax execute="@this" render="updateThisOnSuccess messages" /&gt; Validation Failed &lt;f:ajax execute="@this" render="messages" /&gt; 【参考方案1】:

试试这个

<h:panelGroup id="updateThisOnSuccess">
    <ui:fragment rendered="#not facesContext.validationFailed">
        <h:inputText value="#controller.field" />
        <!-- other fields -->
    </ui:fragment>
</h:panelGroup>

【讨论】:

【参考方案2】:

请试试这个。要求是您必须使用 Bean Validation 实现模型验证,并且如果需要,搜索字段必须实现 JSF 验证。 如果您写“123456”,则返回数据,否则不返回任何内容并打印一条消息。

支持 bean:

@Named
@ViewScoped
public class yourBean implements Serializable

    private static final long serialVersionUID = 1L;

    @Size(min=2)
    private String field01;

    private String searchWebService;    

    public void saveF()
        System.out.println("save");
    

    public void searchWebServiceF()

        Boolean successWS = ("123456").equals(this.searchWebService);
        if(successWS)
            this.setField01("WS data");
        else
            FacesContext.getCurrentInstance().
                addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "WS fails", ""));
        
    

    public String getSearchWebService() 
        return searchWebService;
    
    public void setSearchWebService(String searchWebService) 
        this.searchWebService = searchWebService;
    
    public String getField01() 
        return field01;
    
    public void setField01(String field01) 
        this.field01 = field01;
    

在您的页面中:

<h:form id="form01">
<h:messages id="message"/>
    <h:inputText id="wsid" value="#pruebasBorradorBean.searchWebService">
        <f:validateLength maximum="6"/>
        <f:ajax execute="@form" render="@form" listener="#pruebasBorradorBean.searchWebServiceF()" />
    </h:inputText>

    <h:panelGroup id="thedata">
        <h:inputText value="#pruebasBorradorBean.field01">
            <f:validateBean disabled="#param['javax.faces.source']!='form01:save'"/>
        </h:inputText>
        <!-- other fields -->
    </h:panelGroup>
    <h:commandButton id="save" value="submit">
        <f:ajax render="thedata message" execute="@this thedata" listener="#pruebasBorradorBean.saveF()"/>
    </h:commandButton>

</h:form>

【讨论】:

太棒了!在我的示例中,根据要求,您的代码运行良好。但在我的实际应用中,other fields 有很多Converters,例如IntegerDate。你能解释一下如果 field01PruebasBorradorBean 中的 Integer 怎么办?如果用户输入了无效字符,我可以像禁用 Validator 一样“禁用 Converter”吗?在我的测试中,最后一个测试用例不起作用,因为如果用户尝试使用 field01 中的无效字符搜索 WebService,它将指责转换错误。【参考方案3】:

您可以更改将在渲染阶段处理的组件,更改位于getRenderIds() 的PartialViewContext 的集合。根据to documentation,这个集合是可变的

FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().remove("formName:updateThisOnSuccess");

为了测试这个解决方案,我使用了这个控制器:

@Named
@ViewScoped
public class Controller implements Serializable 

    private static final long serialVersionUID = 1L;

    private final static List<String> LIST_VALID_WEB_SERVICE_SEARCHS =
        Arrays.asList(new String[] "foo", "bar");

    private String webServiceParameter;
    private Integer field01;

    public void searchWebService() 

        if (LIST_VALID_WEB_SERVICE_SEARCHS.contains(getWebServiceParameter())) 
            setField01(123);
         else 

            FacesContext facesContext = FacesContext.getCurrentInstance();

            facesContext.getPartialViewContext().getRenderIds().remove("formFields");

            FacesMessage facesMessage = new FacesMessage("Search not found in WebService.");
            facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
            facesContext.addMessage("formName:searchWebService", facesMessage);
        
    

    public void submit() 
        System.out.println("submitted");
    

    // Getters and Setters

并使用了这个视图:

<h:form id="formSearch">
    <h:inputText id="webServiceParameter" value="#controller.webServiceParameter">
        <f:ajax execute="@this" render="formFields messages" listener="#controller.searchWebService" />
    </h:inputText><br />
</h:form>

<h:form id="formFields">
    <h:inputText id="field01" value="#controller.field01" required="true">
        <f:validateLongRange minimum="2" maximum="345" />
    </h:inputText><br />
    <!-- other fields -->

    <h:commandButton value="submit" action="#controller.submit">
        <f:ajax render="@form messages" execute="@form" />
    </h:commandButton>
</h:form>

<h:messages id="messages" />

【讨论】:

能否在WS成功后编写额外的代码模拟模型更新?你看过我的解决方案了吗? @lametaweb 我已经编辑了我的答案以满足您的评论。 好的。我认为这是一个非常好的解决方案。 @BalusC 你说这个问题很啰嗦。你认为这个解决方案是重复的答案,还是相反地在场景中加入了新的东西?【参考方案4】:

你可以这样做:

&lt;f:ajax execute="@this" render="#controller.success message"/&gt;

其中success 是一个字符串属性,如果 WS 失败则为空,否则为“updateThisOnSuccess”。

或者您可以摆脱用于通知用户 WS 失败的 JSF 验证机制。想一想,这并不是对模型的真正验证。您可以使用支持 bean 中的布尔标志属性在 WS Id 字段旁边以红色或类似的颜色绘制一个图标。

【讨论】:

请先测试代码,然后再作为答案。如果您无法从头顶判断给定的代码是否有效,最好发表“试试这个”评论。

以上是关于仅在验证成功时渲染组件的主要内容,如果未能解决你的问题,请参考以下文章

即使在表单活动验证状态下,如何仅在提交时验证角度表单

Angular 反应式表单自定义验证器。仅在选中复选框时启用验证

具有渲染属性的jsf组件验证失败

仅在组件尚未重新渲染时才渲染它

22.Django(form组件)

仅在重新渲染组件时才反应状态更新