在 JSF2 的 bean 中清除后,值仍保留在表单字段中

发布于 2024-10-26 15:18:58 字数 924 浏览 2 评论 0原文

在我的 JSF2 应用程序中,我有“清除”按钮,该按钮应该清除所有字段。然而,它并不总是有效。

我的页面片段:

<h:form id="bi">
  <h:inputText value="#{bean.entity.firstname}" />
  <h:inputText value="#{bean.entity.surname}" />

  <h:commandButton value="Clear" immediate="true" action="#{bean.clear}">
    <f:ajax render="bi" />
  </h:commandButton>
  <h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>

以及 bean 中的 clear() 方法:

public void clear() {
  entity = new Entity();
}

如果我在字段中输入值,然后单击“清除”,所有内容都会按预期清除。然而,考虑这样的场景: 1. 仅在一个字段中输入值(实体上的 JSR303 注释需要这两个字段)。 2. 单击“提交”。出现错误消息。 3. 单击“清除”。

输入的值保留。为什么没有清除?

此外,如果我手动清除它,然后单击“清除”,它会返回到该字段。我检查了单击“清除”按钮后浏览器是否有部分响应。我怀疑这与视图状态有关。

此外,如果我将 validator="#{bean.validate}" 添加到该字段,它就会进入此验证。即使按钮具有 immediate="true" 属性。为什么?立即按钮不应该忽略验证吗?

In my JSF2 application, I have "Clear" button, which is supposed to clear all the fields. However, it doesn't always work.

My page fragment:

<h:form id="bi">
  <h:inputText value="#{bean.entity.firstname}" />
  <h:inputText value="#{bean.entity.surname}" />

  <h:commandButton value="Clear" immediate="true" action="#{bean.clear}">
    <f:ajax render="bi" />
  </h:commandButton>
  <h:commandButton value="Submit" action="#{bean.submit}" />
</h:form>

And clear() method in my bean:

public void clear() {
  entity = new Entity();
}

If I enter values in the fields, and click "Clear", everything is cleared as expected. However, consider such scenario:
1. Enter value only in one field (both are required by JSR303 annotations on entity).
2. Click "Submit". Error message appears.
3. Click "Clear".

Entered value remains. Why is it not cleared?

Moreover, if I clear it by hand, and click "Clear", it returns to the field. I checked that it comes to the browser in partial response after clicking "Clear" button. I suspect it has something to do with view state.

Moreover, if I add validator="#{bean.validate}" to the field, it enter this validation. Even if button has immediate="true" attribute. Why? Shouldn't immediate button ommit validation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花开雨落又逢春i 2024-11-02 15:18:58

您或多或少遇到了一个有关更新已进行验证的组件的众所周知的问题。

这篇文章相当旧,但仍然相关:http://ishabalov .blogspot.com/2007/08/sad-story-about-uiinput.html

这里发布了一个社区为 JSF 1.2 中的 A4J 创建的解决方案:http://community.jboss.org/thread/8446?start=15&tstart =0

但不幸的是,这不能直接在 JSF 2.0 中工作,并且在您的情况下它根本不起作用,因为它是 A4J 特定的。尽管如此,它可能是灵感的源泉。

基本上,您需要遍历组件树并清除其状态。最巧妙的事情是准确地清除要重新渲染的组件的状态。但是,如果您的特定应用程序或页面可以容忍,您可以采用暴力方法并清除所有内容。

You've run into a more or less well-known issue regarding updating components for which validation has already happened.

This post is rather old, but still relevant: http://ishabalov.blogspot.com/2007/08/sad-story-about-uiinput.html

There is a community created solution for A4J in JSF 1.2 posted here: http://community.jboss.org/thread/8446?start=15&tstart=0

But unfortunately, this doesn't work directly in JSF 2.0 and in your case it wouldn't work at all since it's A4J specific. Nevertheless it might be a source of inspiration.

Basically you need to walk the component tree and clear its state. The neatest thing is to clear exactly the state of the components that you are going to re-render. But you might take the brute-force approach and just clear all if your particular application or page can tolerate that.

南街女流氓 2024-11-02 15:18:58

我最终不得不避免提交或采取行动来正确清除表格。我使用带有 void bean 方法的 actionListener 来代替。

但后来我遇到了有条件地需要导航的问题,这通常是通过操作中的 String 方法来完成的。我使用ExternalContext.redirect()来完成我从以下内容中学到的内容:

JSF PostConstruct 异常处理 -重定向

JSF 导航重定向到上一页

我的页面代码:

            <p:commandButton value="Login" update=":loginForm"
                            actionListener="#{loginBean.login}"/>

我的豆代码:

public void login() {
    RtsLDAPAD laLdap = new RtsLDAPAD();
    boolean lbAuthenticated = false;
    try
    {           
        lbAuthenticated = laLdap.login(userName, password);
        System.out.println(
            "The Result is " + lbAuthenticated + " for " + userName);
    }
    catch (Exception aeRTSEx)
    {
        aeRTSEx.printStackTrace();
    }

    if (lbAuthenticated) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect("taskform.jsf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        facesContext.addMessage(null,
                new FacesMessage("Login failed for " + userName + "."));
        UIViewRoot uiViewRoot = facesContext.getViewRoot();

        HtmlInputText inputText = null;
        Password pwd = null;
        inputText = (HtmlInputText) uiViewRoot.findComponent("loginForm:username");
        inputText.setSubmittedValue(null);
        inputText.setValue(null);
        inputText.setLocalValueSet(false);
        inputText.setValid(true);

        pwd = (Password) uiViewRoot.findComponent("loginForm:password");
        pwd.setSubmittedValue(null);
        pwd.setValue(null);
        pwd.setLocalValueSet(false);
        pwd.setValid(true);

        userName = null;
        password = null;            
    }
}

I wound up having to avoid submit or action to get the form to clear properly. I used actionListener with a void bean method instead.

But then I faced the problem of conditionally needing navigation which is usually done with a String method from action. I used ExternalContext.redirect() to accomplish that which I learned from the following:

JSF PostConstruct Exception Handling - Redirect

JSF navigation redirect to previous page

my page code:

            <p:commandButton value="Login" update=":loginForm"
                            actionListener="#{loginBean.login}"/>

my bean code:

public void login() {
    RtsLDAPAD laLdap = new RtsLDAPAD();
    boolean lbAuthenticated = false;
    try
    {           
        lbAuthenticated = laLdap.login(userName, password);
        System.out.println(
            "The Result is " + lbAuthenticated + " for " + userName);
    }
    catch (Exception aeRTSEx)
    {
        aeRTSEx.printStackTrace();
    }

    if (lbAuthenticated) {
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect("taskform.jsf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {

        FacesContext facesContext = FacesContext.getCurrentInstance();
        facesContext.addMessage(null,
                new FacesMessage("Login failed for " + userName + "."));
        UIViewRoot uiViewRoot = facesContext.getViewRoot();

        HtmlInputText inputText = null;
        Password pwd = null;
        inputText = (HtmlInputText) uiViewRoot.findComponent("loginForm:username");
        inputText.setSubmittedValue(null);
        inputText.setValue(null);
        inputText.setLocalValueSet(false);
        inputText.setValid(true);

        pwd = (Password) uiViewRoot.findComponent("loginForm:password");
        pwd.setSubmittedValue(null);
        pwd.setValue(null);
        pwd.setLocalValueSet(false);
        pwd.setValid(true);

        userName = null;
        password = null;            
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文