You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@click.apache.org by dshah <di...@exit41.com> on 2009/12/08 20:20:37 UTC

Stateful pages - examples?

Hi,
Are there any examples with stateful pages?  

I have a test case where I have one page (A) that is stateful and I call
another page(B) (via ajax) to load section of a form that is a member of
page A.  I have put all the construction of control objects on the onInit()
method.. All works fine when to render this pages but when I click on a
button to submit the form, I get an error that the "form already contains
field".. How can we use stateful pages with form where you want to create
the field controls on the onInit() method (since they may change based on
user input..)

Here is what my code looks like:
Page A: (AjaxTestPage.java)
public class AjaxTestPage extends Page
{
	
	public Form form =  new Form("form");
	Submit addToOrderSubmit = new Submit("addThisToOrder", this,
"onAddThisToOrder");
	
	public AjaxTestPage()
	{
		setStateful(true);
		
	}
	public void onInit()
	{
		super.onInit();
		addMinMaxDropDownsToForm();
		form.add(addToOrderSubmit);
	}
	
	private void addMinMaxDropDownsToForm()
	{
		SelectGroup sg = new SelectGroup("selectOption");
		sg.setLabel("SelectGroupLabel");
		sg.setName("SelectGroupName");
		for (int i = 0; i < 10; i++) {
			String name = "Name" + i;
			Integer intI = new Integer(i);
			String intString = intI.toString();
			Select select = new Select(intString, name);
			select.setWidth("30");
			//select.setAttribute("onChange", "selectMinMaxCondiment('" + i	+ "')");
			for (int j = 0; j <= 2; j++) {
				select.add(new Option(String.valueOf(j), String.valueOf(j)));
			}
			sg.add(select);	
		}
		form.add(sg);
	}
	
	public boolean onAddThisToOrder() 
	{ 
           //do something here
        }
       public Form getForm() {
		return this.form;
	}
}

Page B (AjaxTestPopulate.java) which populate a new control on the form:
public class AjaxTestPopulate extends Page {

	public CheckList childList = null;
	public Form form = null;
	
	public AjaxTestPopulate() {
		
	}
	
	@Override
	public void onInit() {
		childList = getChildList(); 
		form = getParentForm();
		form.add(childList);
	}
	public Form getParentForm() {
		AjaxTestPage page = (AjaxTestPage)
getContext().getSessionAttribute(AjaxTestPage.class.getName()); 
	    return page.getForm(); 
	}
	public CheckList getChildList() {
		childList = new CheckList();
		childList.setLabel("checkListName");
		childList.setName("checkListName");
		childList.setHeight(null);
		childList.setSortable(false);
		for (int i= 0; i < 2; i++) {
			
			Option select = new Option("selectionGroupChildId",  "name"+i);
			childList.add(select);
		}
		return childList;
	}

    public String getContentType() {
        return "text/html; charset=UTF-8";
    }

}


Any idea how to do this using stateful pages?

Dipita
-- 
View this message in context: http://n2.nabble.com/Stateful-pages-examples-tp4134634p4134634.html
Sent from the click-user mailing list archive at Nabble.com.

Re: Stateful pages - examples?

Posted by dshah <di...@exit41.com>.
Hi Bob,
Do you know how expensive it is from a network/bandwidth etc perspective to
cache an object on the httpSession vs use a stateful page with Click?  

Dipita

Bob Schellink-2 wrote:
> 
> 
> dshah wrote:
>> 
>> I was doing this except I realized my problem - I was setting the
>> attribute
>> in the httpSession in the constructor of PageOne so obviously when
>> pageOne
>> is refreshed, this attribute was getting overwritten.  I changed my test
>> to
>> put the form object in the HttpSession before calling the constructor of
>> PageOne (in a page before that) and now it seems to work fine.
> 
> 
> Glad that worked. You can also conditionally add the Form to the session
> by invoking:
> 
>    Context context = getContext();
>    if (! context.hasSessionAttribute(FORM_KEY)) {
>      context.setSessionAttribute(FORM_KEY, form);
>    }
> 
> kind regards
> 
> bob
> 
> 

-- 
View this message in context: http://n2.nabble.com/Stateful-pages-examples-tp4134634p4149046.html
Sent from the click-user mailing list archive at Nabble.com.

Re: Stateful pages - examples?

Posted by Bob Schellink <sa...@gmail.com>.
dshah wrote:
> 
> I was doing this except I realized my problem - I was setting the attribute
> in the httpSession in the constructor of PageOne so obviously when pageOne
> is refreshed, this attribute was getting overwritten.  I changed my test to
> put the form object in the HttpSession before calling the constructor of
> PageOne (in a page before that) and now it seems to work fine.


Glad that worked. You can also conditionally add the Form to the session by invoking:

   Context context = getContext();
   if (! context.hasSessionAttribute(FORM_KEY)) {
     context.setSessionAttribute(FORM_KEY, form);
   }

kind regards

bob

Re: Stateful pages - examples?

Posted by dshah <di...@exit41.com>.
Regarding: 
"Click is not aware of controls placed in the HttpSession. You need to
retrieve the Form from the
Session on PageTwo to manipulate it further eg:"

I was doing this except I realized my problem - I was setting the attribute
in the httpSession in the constructor of PageOne so obviously when pageOne
is refreshed, this attribute was getting overwritten.  I changed my test to
put the form object in the HttpSession before calling the constructor of
PageOne (in a page before that) and now it seems to work fine.

Thanks for responding!
Dipita


Bob Schellink-2 wrote:
> 
> dshah wrote:
>> Hi Bob,
>> For "You don't have to make the Page stateful in order to retrieve the
>> Form
>> from another Page. Another
>> option is to put the Form in the HttpSession and retrieve that Form from
>> another Page: " -- I tried this for my example and while it renders fine
>> on
>> the html (page two's content show up,) the pageOne's form on the server
>> side
>> doesn't have the newly added controls.. When Click looks at the objects
>> on
>> the container, does it get them from the session or do we explicitly need
>> to
>> get the object from the session and look at that object? 
> 
> 
> Click is not aware of controls placed in the HttpSession. You need to
> retrieve the Form from the 
> Session on PageTwo to manipulate it further eg:
> 
> public PageTwo extends BorderPage {
> 
>    public void onInit() {
>      Form form = getSharedForm();
>      ...
>    }
> 
>    private Form getSharedForm() {
>      return (Form) getContext().getSessionAttribute(PageOne.FORM_KEY);
>    }
> }
> 
> kind regards
> 
> bob
> 
> 

-- 
View this message in context: http://n2.nabble.com/Stateful-pages-examples-tp4134634p4148918.html
Sent from the click-user mailing list archive at Nabble.com.

Re: Stateful pages - examples?

Posted by Bob Schellink <sa...@gmail.com>.
dshah wrote:
> Hi Bob,
> For "You don't have to make the Page stateful in order to retrieve the Form
> from another Page. Another
> option is to put the Form in the HttpSession and retrieve that Form from
> another Page: " -- I tried this for my example and while it renders fine on
> the html (page two's content show up,) the pageOne's form on the server side
> doesn't have the newly added controls.. When Click looks at the objects on
> the container, does it get them from the session or do we explicitly need to
> get the object from the session and look at that object? 


Click is not aware of controls placed in the HttpSession. You need to retrieve the Form from the 
Session on PageTwo to manipulate it further eg:

public PageTwo extends BorderPage {

   public void onInit() {
     Form form = getSharedForm();
     ...
   }

   private Form getSharedForm() {
     return (Form) getContext().getSessionAttribute(PageOne.FORM_KEY);
   }
}

kind regards

bob

Re: Stateful pages - examples?

Posted by dshah <di...@exit41.com>.
Hi Bob,
For "You don't have to make the Page stateful in order to retrieve the Form
from another Page. Another
option is to put the Form in the HttpSession and retrieve that Form from
another Page: " -- I tried this for my example and while it renders fine on
the html (page two's content show up,) the pageOne's form on the server side
doesn't have the newly added controls.. When Click looks at the objects on
the container, does it get them from the session or do we explicitly need to
get the object from the session and look at that object? 

Any thoughts?
Dipita

Bob Schellink-2 wrote:
> 
> Hi Dipita,
> 
> dshah wrote:
>> Hi Bob,
>> What is the difference between addControl and insert on the Form object?
> 
> #add adds the control at the end of the list. It delegates to insert e.g:
> 
> public Control add(Control c) {
>    return insert(c, getControls().size());
> }
> 
> If you want to remove a Control you can invoke the #remove method:
> 
> form.add(field);
> form.remove(field);
> 
> Containers in Click is backed by both a list and a map. Reason being that
> list keeps the order of 
> the controls, while map provides instant lookup access.
> 
> In your example below you remove it from the ControlMap but not the
> Controls list. However it is 
> easier to invoke the container's #remove method which takes care of this
> detail.
> 
>> 
>> I am still not clear when the form objects get cleared on a stateful
>> page..
> 
> You mean when does field values get cleared? On a stateful Page the fields
> won't be cleared. However 
> during the onProcess event (which follows the onInit event) the field
> values are updated to incoming 
> request parameters.
> 
> Form has the method #clearValues, but that method clears all fields
> including HiddenFields, which is 
> not always desired.
> 
> I sometimes add a method to my Page which has more control over which Form
> values are cleared. (you 
> can add this to a custom Form as well):
> 
>     public void onInit() {
>       ...
>       clearVisibleFields();
>       ...
>     }
> 
>     private void clearVisibleFields() {
>          // Retrieve all <input> fields from Form
>          List fields = ContainerUtils.getInputFields(form);
>          Field field = null;
>          for (int i = 0, size = fields.size(); i < size; i++) {
>              field = (Field) fields.get(i);
> 
>              // Careful not to clear hidden field values
>              if (!(field instanceof HiddenField)) {
>                  field.setValue(null);
>              }
>          }
>          // idField is a HiddenField that needs to be cleared
>          idField.setValue(null);
>      }
> 
>> 
>> I am trying to make my form sort of act like a 'stateless' form but I
>> need
>> to make the page stateful so I can access the form object from another
>> page.. How can I remove all the elements from a form without having to
>> instantiate the form object on the onInit method.
> 
> 
> You don't have to make the Page stateful in order to retrieve the Form
> from another Page. Another 
> option is to put the Form in the HttpSession and retrieve that Form from
> another Page:
> 
> public PageOne extends Page {
> 
>    public static final String FORM_KEY = "PageOne.form";
> 
>    private Form form = new From("form");
> 
>    public PageOne() {
>      getContext().setSessionAttribute(FORM_KEY, form);
>    }
> }
> 
> public PageTwo extends Page {
> 
>    private Form form;
> 
>    public PageOne() {
>      form = (Form) getContext().getSessionAttribute(PageOne.FORM_KEY);
>    }
> }
> 
> kind regards
> 
> bob
> 
> 

-- 
View this message in context: http://n2.nabble.com/Stateful-pages-examples-tp4134634p4147913.html
Sent from the click-user mailing list archive at Nabble.com.

Re: Stateful pages - examples?

Posted by Bob Schellink <sa...@gmail.com>.
Hi Dipita,

dshah wrote:
> Hi Bob,
> What is the difference between addControl and insert on the Form object?

#add adds the control at the end of the list. It delegates to insert e.g:

public Control add(Control c) {
   return insert(c, getControls().size());
}

If you want to remove a Control you can invoke the #remove method:

form.add(field);
form.remove(field);

Containers in Click is backed by both a list and a map. Reason being that list keeps the order of 
the controls, while map provides instant lookup access.

In your example below you remove it from the ControlMap but not the Controls list. However it is 
easier to invoke the container's #remove method which takes care of this detail.

> 
> I am still not clear when the form objects get cleared on a stateful page..

You mean when does field values get cleared? On a stateful Page the fields won't be cleared. However 
during the onProcess event (which follows the onInit event) the field values are updated to incoming 
request parameters.

Form has the method #clearValues, but that method clears all fields including HiddenFields, which is 
not always desired.

I sometimes add a method to my Page which has more control over which Form values are cleared. (you 
can add this to a custom Form as well):

    public void onInit() {
      ...
      clearVisibleFields();
      ...
    }

    private void clearVisibleFields() {
         // Retrieve all <input> fields from Form
         List fields = ContainerUtils.getInputFields(form);
         Field field = null;
         for (int i = 0, size = fields.size(); i < size; i++) {
             field = (Field) fields.get(i);

             // Careful not to clear hidden field values
             if (!(field instanceof HiddenField)) {
                 field.setValue(null);
             }
         }
         // idField is a HiddenField that needs to be cleared
         idField.setValue(null);
     }

> 
> I am trying to make my form sort of act like a 'stateless' form but I need
> to make the page stateful so I can access the form object from another
> page.. How can I remove all the elements from a form without having to
> instantiate the form object on the onInit method.


You don't have to make the Page stateful in order to retrieve the Form from another Page. Another 
option is to put the Form in the HttpSession and retrieve that Form from another Page:

public PageOne extends Page {

   public static final String FORM_KEY = "PageOne.form";

   private Form form = new From("form");

   public PageOne() {
     getContext().setSessionAttribute(FORM_KEY, form);
   }
}

public PageTwo extends Page {

   private Form form;

   public PageOne() {
     form = (Form) getContext().getSessionAttribute(PageOne.FORM_KEY);
   }
}

kind regards

bob

Re: Stateful pages - examples?

Posted by dshah <di...@exit41.com>.
Hi Bob,
What is the difference between addControl and insert on the Form object?

I am still not clear when the form objects get cleared on a stateful page..
In created a simplistic example of what we have -- (our existing code is
much more complicated and uses hidden values etc):

public class AjaxTestPage extends Page
{
        public E41Form form =  new E41Form("form");
	Submit addToOrderSubmit = new Submit("addThisToOrder", this,
"onAddThisToOrder");
	
	public AjaxTestPage()
	{
		setStateful(true);
		
	}
	public void onInit()
	{
		super.onInit();
	        TextField field = new TextField("name"); 
                form.add(field);
		form.add(addToOrderSubmit);
	}
       public boolean onAddThisToOrder() 
	{
            //do something after button is clicked
        }
}

my E41Form has the following:
public class E41Form extends Form 
{
	private static final long serialVersionUID = 1L;
	public E41Form(String name) {
		super(name);
	}
	public E41Form() {
		super();
	}
	@Override 
	public Control add(Control control) {  
		
		if (getControlMap().containsKey(control.getName())) { 
			Control existingControl = (Control)
getControlMap().get(control.getName());
			if(existingControl.equals(control)) {
				return existingControl;  //return only if the control is the same
			} else {
				getControlMap().remove(existingControl.getName()); //otherwise remove
the old control and add new one - in our case we need to do this because we
reuse hiddden fields but their values may change.
				return (super.add(control));
			}			
		}  else {
			return (super.add(control));
		}
	} 
}

So in my example above, it seems that a new textfield is added after the
submit button listener is invoked.. so when it renders again, it's now got
two texfield..

I am trying to make my form sort of act like a 'stateless' form but I need
to make the page stateful so I can access the form object from another
page.. How can I remove all the elements from a form without having to
instantiate the form object on the onInit method.

Thoughts?
Dipita


dshah wrote:
> 
> Ok. Thanks Bob! I'll try that.
> 
> Dipita
> 
> Bob Schellink-2 wrote:
>> 
>> I think the idea would be that control action events would add fields to
>> the Form, not the onInit
>> method. Otherwise, as you mentioned, Click throws the exception.
>> 
>> public AjaxPage extends Page {
>> 
>>    private ActionLink more = new ActionLink("more", this, "onMoreClick");
>>    private Form form = new Form("form");
>> 
>>    public boolean onMoreClick() {
>>      TextField field = new TextField("name");
>>      form.add(field);
>> 
>>      renderControl(field);
>>    }
>> 
>>    private void renderControl(Control c) {
>>       ...
>>       HttpServletResponse response = getContext().getResponse();
>> 
>>       //write the control to the response
>>       ...
>>       setPath(null);
>>    }
>> }
>> 
>> 
>> onMoreClick is only called when the link is clicked so you shouldn't
>> receive the exception if the 
>> Form is submitted.
>> 
>> That said this discussion is making me think that controls might be
>> better off not throwing the 
>> exception and instead return silently.
>> 
>> You can implement this in a custom Form implementation:
>> 
>> public AjaxForm extends Form {
>> 
>>    @Override
>>    public Control insert(Control control, int index) {
>>      // Return if form contains control
>>      if (getControlMap().contains(control.getName()) {
>>        return control;
>>      }
>> 
>>      // Else insert control
>>      super.insert(control, index);
>>    }
>> }
>> 
>> 
>> kind regards
>> 
>> bob
>> 
>> 
>> dshah wrote:
>>> Hi,
>>> Are there any examples with stateful pages?  
>>> 
>>> I have a test case where I have one page (A) that is stateful and I call
>>> another page(B) (via ajax) to load section of a form that is a member of
>>> page A.  I have put all the construction of control objects on the
>>> onInit()
>>> method.. All works fine when to render this pages but when I click on a
>>> button to submit the form, I get an error that the "form already
>>> contains
>>> field".. How can we use stateful pages with form where you want to
>>> create
>>> the field controls on the onInit() method (since they may change based
>>> on
>>> user input..)
>>> 
>>> Here is what my code looks like:
>>> Page A: (AjaxTestPage.java)
>>> public class AjaxTestPage extends Page
>>> {
>>> 	
>>> 	public Form form =  new Form("form");
>>> 	Submit addToOrderSubmit = new Submit("addThisToOrder", this,
>>> "onAddThisToOrder");
>>> 	
>>> 	public AjaxTestPage()
>>> 	{
>>> 		setStateful(true);
>>> 		
>>> 	}
>>> 	public void onInit()
>>> 	{
>>> 		super.onInit();
>>> 		addMinMaxDropDownsToForm();
>>> 		form.add(addToOrderSubmit);
>>> 	}
>>> 	
>>> 	private void addMinMaxDropDownsToForm()
>>> 	{
>>> 		SelectGroup sg = new SelectGroup("selectOption");
>>> 		sg.setLabel("SelectGroupLabel");
>>> 		sg.setName("SelectGroupName");
>>> 		for (int i = 0; i < 10; i++) {
>>> 			String name = "Name" + i;
>>> 			Integer intI = new Integer(i);
>>> 			String intString = intI.toString();
>>> 			Select select = new Select(intString, name);
>>> 			select.setWidth("30");
>>> 			//select.setAttribute("onChange", "selectMinMaxCondiment('" + i	+
>>> "')");
>>> 			for (int j = 0; j <= 2; j++) {
>>> 				select.add(new Option(String.valueOf(j), String.valueOf(j)));
>>> 			}
>>> 			sg.add(select);	
>>> 		}
>>> 		form.add(sg);
>>> 	}
>>> 	
>>> 	public boolean onAddThisToOrder() 
>>> 	{ 
>>>            //do something here
>>>         }
>>>        public Form getForm() {
>>> 		return this.form;
>>> 	}
>>> }
>>> 
>>> Page B (AjaxTestPopulate.java) which populate a new control on the form:
>>> public class AjaxTestPopulate extends Page {
>>> 
>>> 	public CheckList childList = null;
>>> 	public Form form = null;
>>> 	
>>> 	public AjaxTestPopulate() {
>>> 		
>>> 	}
>>> 	
>>> 	@Override
>>> 	public void onInit() {
>>> 		childList = getChildList(); 
>>> 		form = getParentForm();
>>> 		form.add(childList);
>>> 	}
>>> 	public Form getParentForm() {
>>> 		AjaxTestPage page = (AjaxTestPage)
>>> getContext().getSessionAttribute(AjaxTestPage.class.getName()); 
>>> 	    return page.getForm(); 
>>> 	}
>>> 	public CheckList getChildList() {
>>> 		childList = new CheckList();
>>> 		childList.setLabel("checkListName");
>>> 		childList.setName("checkListName");
>>> 		childList.setHeight(null);
>>> 		childList.setSortable(false);
>>> 		for (int i= 0; i < 2; i++) {
>>> 			
>>> 			Option select = new Option("selectionGroupChildId",  "name"+i);
>>> 			childList.add(select);
>>> 		}
>>> 		return childList;
>>> 	}
>>> 
>>>     public String getContentType() {
>>>         return "text/html; charset=UTF-8";
>>>     }
>>> 
>>> }
>>> 
>>> 
>>> Any idea how to do this using stateful pages?
>>> 
>>> Dipita
>> 
>> 
>> 
> 
> 

-- 
View this message in context: http://n2.nabble.com/Stateful-pages-examples-tp4134634p4143126.html
Sent from the click-user mailing list archive at Nabble.com.

Re: Stateful pages - examples?

Posted by dshah <di...@exit41.com>.
Ok. Thanks Bob! I'll try that.

Dipita

Bob Schellink-2 wrote:
> 
> I think the idea would be that control action events would add fields to
> the Form, not the onInit
> method. Otherwise, as you mentioned, Click throws the exception.
> 
> public AjaxPage extends Page {
> 
>    private ActionLink more = new ActionLink("more", this, "onMoreClick");
>    private Form form = new Form("form");
> 
>    public boolean onMoreClick() {
>      TextField field = new TextField("name");
>      form.add(field);
> 
>      renderControl(field);
>    }
> 
>    private void renderControl(Control c) {
>       ...
>       HttpServletResponse response = getContext().getResponse();
> 
>       //write the control to the response
>       ...
>       setPath(null);
>    }
> }
> 
> 
> onMoreClick is only called when the link is clicked so you shouldn't
> receive the exception if the 
> Form is submitted.
> 
> That said this discussion is making me think that controls might be better
> off not throwing the 
> exception and instead return silently.
> 
> You can implement this in a custom Form implementation:
> 
> public AjaxForm extends Form {
> 
>    @Override
>    public Control insert(Control control, int index) {
>      // Return if form contains control
>      if (getControlMap().contains(control.getName()) {
>        return control;
>      }
> 
>      // Else insert control
>      super.insert(control, index);
>    }
> }
> 
> 
> kind regards
> 
> bob
> 
> 
> dshah wrote:
>> Hi,
>> Are there any examples with stateful pages?  
>> 
>> I have a test case where I have one page (A) that is stateful and I call
>> another page(B) (via ajax) to load section of a form that is a member of
>> page A.  I have put all the construction of control objects on the
>> onInit()
>> method.. All works fine when to render this pages but when I click on a
>> button to submit the form, I get an error that the "form already contains
>> field".. How can we use stateful pages with form where you want to create
>> the field controls on the onInit() method (since they may change based on
>> user input..)
>> 
>> Here is what my code looks like:
>> Page A: (AjaxTestPage.java)
>> public class AjaxTestPage extends Page
>> {
>> 	
>> 	public Form form =  new Form("form");
>> 	Submit addToOrderSubmit = new Submit("addThisToOrder", this,
>> "onAddThisToOrder");
>> 	
>> 	public AjaxTestPage()
>> 	{
>> 		setStateful(true);
>> 		
>> 	}
>> 	public void onInit()
>> 	{
>> 		super.onInit();
>> 		addMinMaxDropDownsToForm();
>> 		form.add(addToOrderSubmit);
>> 	}
>> 	
>> 	private void addMinMaxDropDownsToForm()
>> 	{
>> 		SelectGroup sg = new SelectGroup("selectOption");
>> 		sg.setLabel("SelectGroupLabel");
>> 		sg.setName("SelectGroupName");
>> 		for (int i = 0; i < 10; i++) {
>> 			String name = "Name" + i;
>> 			Integer intI = new Integer(i);
>> 			String intString = intI.toString();
>> 			Select select = new Select(intString, name);
>> 			select.setWidth("30");
>> 			//select.setAttribute("onChange", "selectMinMaxCondiment('" + i	+
>> "')");
>> 			for (int j = 0; j <= 2; j++) {
>> 				select.add(new Option(String.valueOf(j), String.valueOf(j)));
>> 			}
>> 			sg.add(select);	
>> 		}
>> 		form.add(sg);
>> 	}
>> 	
>> 	public boolean onAddThisToOrder() 
>> 	{ 
>>            //do something here
>>         }
>>        public Form getForm() {
>> 		return this.form;
>> 	}
>> }
>> 
>> Page B (AjaxTestPopulate.java) which populate a new control on the form:
>> public class AjaxTestPopulate extends Page {
>> 
>> 	public CheckList childList = null;
>> 	public Form form = null;
>> 	
>> 	public AjaxTestPopulate() {
>> 		
>> 	}
>> 	
>> 	@Override
>> 	public void onInit() {
>> 		childList = getChildList(); 
>> 		form = getParentForm();
>> 		form.add(childList);
>> 	}
>> 	public Form getParentForm() {
>> 		AjaxTestPage page = (AjaxTestPage)
>> getContext().getSessionAttribute(AjaxTestPage.class.getName()); 
>> 	    return page.getForm(); 
>> 	}
>> 	public CheckList getChildList() {
>> 		childList = new CheckList();
>> 		childList.setLabel("checkListName");
>> 		childList.setName("checkListName");
>> 		childList.setHeight(null);
>> 		childList.setSortable(false);
>> 		for (int i= 0; i < 2; i++) {
>> 			
>> 			Option select = new Option("selectionGroupChildId",  "name"+i);
>> 			childList.add(select);
>> 		}
>> 		return childList;
>> 	}
>> 
>>     public String getContentType() {
>>         return "text/html; charset=UTF-8";
>>     }
>> 
>> }
>> 
>> 
>> Any idea how to do this using stateful pages?
>> 
>> Dipita
> 
> 
> 

-- 
View this message in context: http://n2.nabble.com/Stateful-pages-examples-tp4134634p4136472.html
Sent from the click-user mailing list archive at Nabble.com.

Re: Stateful pages - examples?

Posted by Bob Schellink <sa...@gmail.com>.
I think the idea would be that control action events would add fields to the Form, not the onInit
method. Otherwise, as you mentioned, Click throws the exception.

public AjaxPage extends Page {

   private ActionLink more = new ActionLink("more", this, "onMoreClick");
   private Form form = new Form("form");

   public boolean onMoreClick() {
     TextField field = new TextField("name");
     form.add(field);

     renderControl(field);
   }

   private void renderControl(Control c) {
      ...
      HttpServletResponse response = getContext().getResponse();

      //write the control to the response
      ...
      setPath(null);
   }
}


onMoreClick is only called when the link is clicked so you shouldn't receive the exception if the 
Form is submitted.

That said this discussion is making me think that controls might be better off not throwing the 
exception and instead return silently.

You can implement this in a custom Form implementation:

public AjaxForm extends Form {

   @Override
   public Control insert(Control control, int index) {
     // Return if form contains control
     if (getControlMap().contains(control.getName()) {
       return control;
     }

     // Else insert control
     super.insert(control, index);
   }
}


kind regards

bob


dshah wrote:
> Hi,
> Are there any examples with stateful pages?  
> 
> I have a test case where I have one page (A) that is stateful and I call
> another page(B) (via ajax) to load section of a form that is a member of
> page A.  I have put all the construction of control objects on the onInit()
> method.. All works fine when to render this pages but when I click on a
> button to submit the form, I get an error that the "form already contains
> field".. How can we use stateful pages with form where you want to create
> the field controls on the onInit() method (since they may change based on
> user input..)
> 
> Here is what my code looks like:
> Page A: (AjaxTestPage.java)
> public class AjaxTestPage extends Page
> {
> 	
> 	public Form form =  new Form("form");
> 	Submit addToOrderSubmit = new Submit("addThisToOrder", this,
> "onAddThisToOrder");
> 	
> 	public AjaxTestPage()
> 	{
> 		setStateful(true);
> 		
> 	}
> 	public void onInit()
> 	{
> 		super.onInit();
> 		addMinMaxDropDownsToForm();
> 		form.add(addToOrderSubmit);
> 	}
> 	
> 	private void addMinMaxDropDownsToForm()
> 	{
> 		SelectGroup sg = new SelectGroup("selectOption");
> 		sg.setLabel("SelectGroupLabel");
> 		sg.setName("SelectGroupName");
> 		for (int i = 0; i < 10; i++) {
> 			String name = "Name" + i;
> 			Integer intI = new Integer(i);
> 			String intString = intI.toString();
> 			Select select = new Select(intString, name);
> 			select.setWidth("30");
> 			//select.setAttribute("onChange", "selectMinMaxCondiment('" + i	+ "')");
> 			for (int j = 0; j <= 2; j++) {
> 				select.add(new Option(String.valueOf(j), String.valueOf(j)));
> 			}
> 			sg.add(select);	
> 		}
> 		form.add(sg);
> 	}
> 	
> 	public boolean onAddThisToOrder() 
> 	{ 
>            //do something here
>         }
>        public Form getForm() {
> 		return this.form;
> 	}
> }
> 
> Page B (AjaxTestPopulate.java) which populate a new control on the form:
> public class AjaxTestPopulate extends Page {
> 
> 	public CheckList childList = null;
> 	public Form form = null;
> 	
> 	public AjaxTestPopulate() {
> 		
> 	}
> 	
> 	@Override
> 	public void onInit() {
> 		childList = getChildList(); 
> 		form = getParentForm();
> 		form.add(childList);
> 	}
> 	public Form getParentForm() {
> 		AjaxTestPage page = (AjaxTestPage)
> getContext().getSessionAttribute(AjaxTestPage.class.getName()); 
> 	    return page.getForm(); 
> 	}
> 	public CheckList getChildList() {
> 		childList = new CheckList();
> 		childList.setLabel("checkListName");
> 		childList.setName("checkListName");
> 		childList.setHeight(null);
> 		childList.setSortable(false);
> 		for (int i= 0; i < 2; i++) {
> 			
> 			Option select = new Option("selectionGroupChildId",  "name"+i);
> 			childList.add(select);
> 		}
> 		return childList;
> 	}
> 
>     public String getContentType() {
>         return "text/html; charset=UTF-8";
>     }
> 
> }
> 
> 
> Any idea how to do this using stateful pages?
> 
> Dipita