Question

I have a listing page that goes to an add page. The add page has a name textbox whose value is bound to a session scoped bean.

The listing page has an add button that goes via an action method to the add page. This action method clears the object that the name textbox is bound to.

I also have a cancel button on the add page, which is bound to an action method that again clears the value that the name textbox is bound to.

If nothing is set to immediate, this all works fine.

However, if I set the cancel button to immediate, if I enter values in the name field, and then click cancel, the action method is fired and clears the object in the backing bean and goes to the listing page. If I then click add, the action method clears the object again (ignore if it's best method or not) and then goes to the add page. I would now expect the add page's name textbox to be empty, but it's not?! Surely, since the add button is not immediate, the values should be re-bound and empty?

Below is the relevant XHTML for the add button on the listing page

<h:commandButton id="addButton"
                 value="Add"
                 action="#{myBean.gotoAdd}"/>

Below is the relevant XHTML for the input box on the add page (myBean is session scoped), followed by that of the cancel button on the add page.:

<h:inputText id="newName"
             value="#{myBean.newObject.name}"
             binding="#{myBean.newNameInput}"
             styleClass="name" />

<h:commandButton id="cancelButton"
                 value="Cancel" immediate="true"
                 action="#{myBean.cancelAdd}"
                 onclick="return confirm('You sure?');"/>
Was it helpful?

Solution

I almost never use the binding property of tags, except for when I need to identify which item of a list has had an action fired on it, so I am not particularly well-informed about its uses. But I know that without using binding your code would most likely work as you expected, so my expectation is that whatever javax.faces.component.UIxxx object you are binding to isn't getting reset correctly.

OTHER TIPS

I'm having very similar problems right now.

Besides removing the binding and/or immediate attribute, try calling setSubmittedValue() on component with binding from action called upon click on 'add' button.

Alas, even if it helps you, you would still have to do it in any action that can lead to displaying same component after cancel.

That's why I'm still trying to figure out some better solution...

If you use immediate="true" then the value will be kept, this is how the parameter works. You should take a look at the following links:

http://wiki.apache.org/myfaces/How_The_Immediate_Attribute_Works

http://wiki.apache.org/myfaces/ClearInputComponents

Ok, here's an example that I did from scratch. I have two cancel buttons, one that is immediate, and one that isn't. Example of steps to reproduce:

  • Go to james-list page and click Add
  • The add page displays with empty fields. Enter values for all fields and click Add.
  • The listing page displays and is updated to include the new person. Click Add.
  • The add page displays with empty fields. Enter values for all fields and Click Cancel (Immediate)
  • The listing page displays and is unchanged. Click Add.
  • The add page displays however the fields are not empty as I would expect. Click Cancel.
  • The listing page displays and is unchanged. Click Add.
  • The add page displays and NOW the fields are not empty.

James.java:

package com.jamiebarrow;

import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;

@ManagedBean
@SessionScoped
public class James {

  private UIComponent idComponent;
  private UIComponent firstNameComponent;
  private UIComponent lastNameComponent;

  public UIComponent getIdComponent() {
    return idComponent;
  }

  public void setIdComponent(UIComponent idComponent) {
    this.idComponent = idComponent;
  }

  public UIComponent getFirstNameComponent() {
    return firstNameComponent;
  }

  public void setFirstNameComponent(UIComponent firstNameComponent) {
    this.firstNameComponent = firstNameComponent;
  }

  public UIComponent getLastNameComponent() {
    return lastNameComponent;
  }

  public void setLastNameComponent(UIComponent lastNameComponent) {
    this.lastNameComponent = lastNameComponent;
  }

  private List<Person> personResults;

  private Person person;

  public James() {
    personResults = new ArrayList();
    personResults.add(new PersonBuilder(1, "Bob", "Uncle").build());
    personResults.add(new PersonBuilder(2, "Jack", "Black").build());
  }

  public List<Person> getPersonResults() {
    return personResults;
  }

  public void setPersonResults(List<Person> personResults) {
    this.personResults = personResults;
  }

  public Person getPerson() {
    return person;
  }

  public void setPerson(Person person) {
    this.person = person;
  }

  private void clearPerson() {
    person = new PersonBuilder().build();
  }

  public String gotoList() {
    return "james-list";
  }

  public String gotoAdd() {
    clearPerson();
    return "james-add";
  }

  public String cancelAdd() {
    clearPerson();
    return gotoList();
  }

  public String addPerson() {
    personResults.add(person);
    return gotoList();
  }
}

james-list.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
<h:head>
  <title>list page</title>
</h:head>

<body>
<div class="container">
  <div class="content">
    <h:messages showSummary="true" showDetail="false" errorClass="error" infoClass="info"
                warnClass="warn"/>
    <h:form>
      <h:dataTable value="#{james.personResults}" var="person">
        <h:column>
          <f:facet name="header">Id</f:facet>
          <h:outputText value="#{person.id}"/>
        </h:column>
        <h:column>
          <f:facet name="header">Name</f:facet>
          <h:outputText value="#{person.firstName}"/>
        </h:column>
        <h:column>
          <f:facet name="header">Surname</f:facet>
          <h:outputText value="#{person.lastName}"/>
        </h:column>
      </h:dataTable>
      <h:panelGroup layout="block">
        <h:commandButton value="Add" action="#{james.gotoAdd}"/>
      </h:panelGroup>
    </h:form>
  </div>
</div>
<ui:debug hotkey="L" rendered="true"/>
</body>
</html>

james-add.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html">
<h:head>
  <title>add page</title>
</h:head>

<body>
<div class="container">
  <div class="content">
    <h:messages showSummary="true" showDetail="false" errorClass="error" infoClass="info"
                warnClass="warn"/>
    <h:form>
      <fieldset>
        <legend>Add Person</legend>
        <h:panelGrid columns="2">
          <h:outputLabel for="PersonId" value="Id:"/>
          <h:inputText id="PersonId" value="#{james.person.id}" binding="#{james.idComponent}"/>
          <h:outputLabel for="PersonFirstName" value="First Name:"/>
          <h:inputText id="PersonFirstName" value="#{james.person.firstName}" binding="#{james.firstNameComponent}"/>
          <h:outputLabel for="PersonLastName" value="Last Name:"/>
          <h:inputText id="PersonLastName" value="#{james.person.lastName}" binding="#{james.lastNameComponent}"/>
        </h:panelGrid>
        <h:panelGroup layout="block">
          <h:commandButton value="Add" action="#{james.addPerson}"/>
          <h:commandButton value="Cancel (immediate)" action="#{james.cancelAdd}" immediate="true"/>
          <h:commandButton value="Cancel" action="#{james.cancelAdd}"/>
        </h:panelGroup>
      </fieldset>
    </h:form>
  </div>
</div>
<ui:debug hotkey="L" rendered="true"/>
</body>
</html>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top