Johan, I think you're making it a bit harder then it needs to be. I've
actually got it working (depending on how you define "working") on my
test machine right now with just that serialization class and a
subclass of form. Since a form has easy access to it's page and all
it's components, it can add javascript to every link it finds for
onClick submits, serialize its page on render on right it to a hidden
field, unserialize the page on beginRequest, and find it's submitting
link on validate to call onClick(). Granted, it would probably be nice
to move some of these things out of the form, page unserialization
probably, but it can be pretty simple.
The only problem I'm having is that I have to use an
IFormSubmitListener, which means that while the page IS restored from
the client, it's first taken from the session, which doesn't really
make any sense. I haven't figured out the "right" way to create a new
page on every request. I'll probably take a look at how bookmarkable
pages work.
-Phil
On 7/1/05, Eelco Hillenius <[EMAIL PROTECTED]> wrote:
Your mailbox is full. We (Martijn and I) keep getting warnings from your
box.
Eelco
Johan Compagner wrote:
i didn't see the patch yet (where is that mail?? sourceforge problem?)
-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
Wicket-develop mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/wicket-develop
------------------------------------------------------------------------
package com.apropobenefits.wicket;
import wicket.AttributeModifier;
import wicket.Component;
import wicket.markup.ComponentTag;
import wicket.markup.MarkupStream;
import wicket.markup.html.form.Form;
import wicket.markup.html.link.Link;
import wicket.markup.parser.XmlTag;
import wicket.model.Model;
public class StatelessForm extends Form {
public StatelessForm(final String id) {
super(id);
}
/**
* Adds an ID and sets the action of the form to a bookmarkable link.
*/
@Override
protected void onComponentTag(final ComponentTag tag) {
super.onComponentTag(tag);
tag.put("action", getPage().urlFor(null, getPage().getClass(),
null));
tag.put("id", "theForm");
}
/**
* Adds some javascript to every link within this form. As well as a
* couple hidden input fields.
*/
@Override
protected void onComponentTagBody(MarkupStream markupStream,
ComponentTag openTag) {
// This gives every link a JavaScript onClick() method and
wipes out
// its origonal href attribute. It would probably be better if
the links
// themselves took care of thier own rendering, but this was
the quickest
// solution.
this.visitChildren(Link.class, new IVisitor() {
public Object component(Component component) {
String script =
"document.getElementById('submittingLink').value = '" +
component.getPageRelativePath() + "';" +
"document.getElementById('theForm').submit();" +
"return false";
component.add(new AttributeModifier("onClick", true,
new Model(script)));
component.add(new AttributeModifier("href", true,
new Model("#")));
return CONTINUE_TRAVERSAL;
}
});
// The pageState hidden field.
XmlTag psInput = new XmlTag();
psInput.setType(XmlTag.OPEN_CLOSE);
psInput.setName("input");
psInput.put("type", "hidden");
psInput.put("name", PageState.REQUEST_KEY);
psInput.put("value", new PageState(getPage()).getString());
renderComponentTag(new ComponentTag(psInput));
// The field that gets populated with the path to the
submitting link.
XmlTag subLink = new XmlTag();
subLink.setType(XmlTag.OPEN_CLOSE);
subLink.setName("input");
subLink.put("type", "hidden");
subLink.put("name", "submittingLink");
subLink.put("id", "submittingLink");
renderComponentTag(new ComponentTag(subLink));
super.onComponentTagBody(markupStream, openTag);
}
/**
* Called by the page factory just after population.
*/
protected void onLinkSubmit() {
Link link = findSubmittingLink();
if (link != null) {
link.onClick();
}
}
/**
* Returns the link that caused this form to be submitted or null
* if it wasn't submitted with a link.
*/
private Link findSubmittingLink() {
final String path = getRequest().getParameter("submittingLink");
return (Link) visitChildren(Link.class, new IVisitor() {
public Object component(final Component component) {
if
(component.getPageRelativePath().equals(path)) {
return component;
}
return CONTINUE_TRAVERSAL;
}
});
}
}
------------------------------------------------------------------------
package com.apropobenefits.wicket;
import wicket.Component;
import wicket.DefaultPageFactory;
import wicket.IPageFactory;
import wicket.Page;
import wicket.PageParameters;
import wicket.Request;
import wicket.RequestCycle;
import wicket.Component.IVisitor;
/**
* A page factory that takes care of state management.
*
* @author Phil Kulak
*/
public class StatelessPageFactory implements IPageFactory {
private IPageFactory internalFactory = new DefaultPageFactory();
public Page newPage(Class c, PageParameters params) {
return populatePage(internalFactory.newPage(c, params));
}
public Page newPage(Class c) {
return populatePage(internalFactory.newPage(c));
}
private Page populatePage(Page page) {
Request request = RequestCycle.get().getRequest();
String ser = request.getParameter(PageState.REQUEST_KEY);
if (ser != null) {
// Return the page to its origonal state.
new PageState(ser).populatePage(page);
// Find the form that submitted. Actually, find the
FIRST stateless
// form. If there's two forms you're out of luck.
page.visitChildren(StatelessForm.class, new IVisitor() {
public Object component(Component component) {
((StatelessForm)
component).onLinkSubmit();
return STOP_TRAVERSAL;
}
});
return page;
}
return page;
}
}