7 Replies Latest reply on Mar 6, 2009 11:17 AM by nbelaevski

    Problem with Rerender of Form Componenets within a ModalPane

    kconway

      Hello,

      I'm having a problem with the rerendering of form components contained within a ModalPanel after executing a richfaces "Cancel" commandButton with the immediate attribute set to true (immediate="true").

      If anyone could give some advice on how to resolve this issue, I would really appreciate it.

      Thanks in advance.

      I've created a skinny application that exemplifies the behavior:

      index.xhtml

      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:f="http://java.sun.com/jsf/core"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:t="http://myfaces.apache.org/tomahawk"
       xmlns:a4j="http://richfaces.org/a4j"
       xmlns:rich="http://richfaces.org/rich"
       xmlns:c="http://java.sun.com/jstl/core">
      <head>
       <title>Foo</title>
      </head>
      <body>
       <f:view>
       <h:form id="baseForm" >
       <t:div id="basePanelDiv">
       <t:panelGrid>
       <t:panelGrid id="fooGrid" columns="2" >
       <h:outputLabel for="baseFieldOne" value="Base Field One: " />
       <h:inputText id="baseFieldOne" value="#{fooController.fieldOne}" size="40" maxlength="40" />
       <h:outputLabel for="baseFieldTwo" value="Base Field Two: " />
       <h:inputText id="baseFieldTwo" value="#{fooController.fieldTwo}" size="40" maxlength="40" />
       </t:panelGrid>
      
       <a4j:commandButton id="fooEditButton" value="Edit..."
       actionListener="#{fooController.editFoo}"
       oncomplete="#{rich:component('fooPanel')}.show()"
       reRender="fooPanel"/>
       </t:panelGrid>
       </t:div>
       </h:form>
       <rich:modalPanel id="fooPanel" autosized="true" moveable="false" >
       <f:facet name="header">
       <h:panelGroup>
       <h:outputText value="Foo Modal Panel" />
       </h:panelGroup>
       </f:facet>
      
       <h:outputText value="Modal Field One: #{fooController.modalFieldOne}" />
      
       <h:form id="fooForm" >
       <t:div id="fooPanelDiv">
       <t:panelGrid>
       <t:panelGrid id="fooTable" columns="2" >
       <h:outputLabel for="modalFieldTwo" value="Modal Field Two: " />
       <h:inputText id="modalFieldTwo" value="#{fooController.modalFieldTwo}" size="40" maxlength="40" />
       </t:panelGrid>
       <t:div >
       <a4j:commandButton id="saveFooEditButton" value="Save"
       actionListener="#{fooController.saveFoo}"
       oncomplete="#{rich:component('fooPanel')}.hide()"
       reRender="fooGrid"/>
       <a4j:commandButton id="cancelFooEditButton" value="Cancel"
       actionListener="#{fooController.cancelFoo}"
       immediate="true"
       oncomplete="#{rich:component('fooPanel')}.hide()"/>
       </t:div>
       </t:panelGrid>
       </t:div>
       </h:form>
       </rich:modalPanel>
       </f:view>
      
      </body>
      
      </html>
      


      FooController.java
      package com;
      
      
      import javax.faces.event.ActionEvent;
      
      import org.springframework.beans.factory.annotation.Configurable;
      import org.springframework.context.annotation.Scope;
      import org.springframework.stereotype.Controller;
      
      @Configurable
      @Controller("fooController")
      @Scope("session")
      public class FooController{
      
       private String fieldOne = "Initial Value for field 1";
       private String fieldTwo = "Initial Value for field 2";
      
       private String modalFieldOne;
       private String modalFieldTwo;
      
      
       public String getFieldOne() {
       return fieldOne;
       }
       public void setFieldOne(String fieldOne) {
       this.fieldOne = fieldOne;
       }
       public String getFieldTwo() {
       return fieldTwo;
       }
       public void setFieldTwo(String fieldTwo) {
       this.fieldTwo = fieldTwo;
       }
      
       public String getModalFieldOne() {
       return modalFieldOne;
       }
       public void setModalFieldOne(String modalFieldOne) {
       this.modalFieldOne = modalFieldOne;
       }
       public String getModalFieldTwo() {
       return modalFieldTwo;
       }
       public void setModalFieldTwo(String modalFieldTwo) {
       this.modalFieldTwo = modalFieldTwo;
       }
      
      
       public void editFoo(ActionEvent event){
       modalFieldOne = new String(fieldOne);
       modalFieldTwo = new String(fieldTwo);
       }
      
       public void saveFoo(ActionEvent event){
       fieldOne = new String(modalFieldOne);
       fieldTwo = new String(modalFieldTwo);
       }
      
       public void cancelFoo(ActionEvent event){
       modalFieldOne = null;
       modalFieldTwo = null;
       }
      
      }
      
      



      Perform the following steps to recreate the behaviour:

      Execute the application index.xhtml
      ----The page should display two fields
      ----Base Field One is editable and contains an initial value as set by fooController.
      ----Base Field Two is editable and contains an initial value as set by fooController.

      Click the "Edit" button
      ----The modal dialog should appear with two fields
      --------Modal Field One is not editable and contains an intial value from "Base Field One" of the first page
      --------Modal Field Two is editable and alos ains an initial value from "Base Field Two" of the first page

      Edit "Modal Field Two" by typing "Modal value" in the input text box then click the "Save" button.

      The basePage is rerendered and "Base Field Two" now contains the value "Modal value" from "Modal Field Two".
      ----So far this is the expected behavior.

      Click the "Edit" button again.
      ----Again the Modal Dialog appears with the expected values.

      Without performing an edit, click the "Cancel" button.

      Before performing any other action, edit "Base Field One" by typing "New Base Value 1" in it's input text box.
      Also, edit "Base Field Two" by typing "New Base Value 2" in it's input text box.

      Click the "Edit" button again.
      ----The Modal Dialog appears but this time
      --------"Modal Field One" contains the value: "New Base Value 1" while
      --------"Modal Field Two" contains the value: "Modal value"

      This IS NOT the expected behaviour. I would have expected "Modal Field Two" to contain the value: "New Base Value 2".

      Observations:
      "Modal Field One" IS NOT located within the "fooForm" while "Modal Field Two" IS located within the "fooForm"

      The "Cancel" button within the "fooForm" submits with immediate="true"
      ----(in my real application, validation is being performed on the ModalDialog form so to cancel, no validation should be performed. In other words immediate="true" on cancel is mandatory).

      Using Eclipse debugger, I am able to observe that the Modal Dialog binding expression "#{fooController.modalFieldOne}" IS EXECUTING the getModalFieldOne() method on fooController while "#{fooController.modalFieldTwo}" DOES NOT EXECUTE the getModalFieldTwo() method.