> Wicket 7.0.0 is about to be released so it's a bit late for ideas. >
=) Is there a board for ideas for next one? > But what you describe sounds like what wicketstuff-stateless project > already provides. > I looked at https://github.com/mafulafunk/wicketstuff-core/tree/master/jdk-1.6-parent/stateless-parent/stateless/src/main/java/org/wicketstuff/stateless It is not quite the same what I am discussing. I mean that if you call page.removeAll() and execute the event, it would still work. We have implemented things like: /** * * Listener that collects fake events. * */ public class FakeEventListener implements IListener { private static final MetaDataKey<FakeEventListener> DATA_KEY = new MetaDataKey<FakeEventListener>() { private static final long serialVersionUID = 1L; }; private ArrayList<String> scripts = new ArrayList<String>(); /** * Constructor * */ private FakeEventListener() { } /** * @see org.apache.wicket.ajax.AjaxRequestTarget.IListener#onBeforeRespond(java.util.Map, * org.apache.wicket.ajax.AjaxRequestTarget) */ @Override public void onBeforeRespond(Map<String, Component> map, AjaxRequestTarget target) { // do nothing } /** * @see org.apache.wicket.ajax.AjaxRequestTarget.IListener#onAfterRespond(java.util.Map, * org.apache.wicket.ajax.AjaxRequestTarget.IJavascriptResponse) */ @Override public void onAfterRespond(Map<String, Component> map, IJavascriptResponse response) { StringBuilder builder = new StringBuilder(); builder.append("var fakeev_inin = function(event) {"); builder.append("if( typeof Tustor == 'undefined' || typeof Tustor.Events == 'undefined') { setTimeout(fakeev_inin, 10); } else {"); for (String parentMarkupId : scripts) { builder.append("Tustor.Events.addFakeEventsClassName('.FACB"); builder.append(index(parentMarkupId)); builder.append("', '"); builder.append(parentMarkupId); builder.append("');"); } builder.append("}};"); builder.append("$(document).ready(function(){fakeev_inin();});"); response.addJavascript(builder.toString()); RequestCycle.get().setMetaData(DATA_KEY, null); } /** * Adds script; * * @param parentMarkupId * */ public void addScript(String parentMarkupId) { if(!scripts.contains(parentMarkupId)) { scripts.add(parentMarkupId); } } /** * * @param parentMarkupId * @return index */ public int index(String parentMarkupId) { if(!scripts.contains(parentMarkupId)) { scripts.add(parentMarkupId); } return scripts.indexOf(parentMarkupId); } /** * Gets and creates if does not exists. * * @return DatePickerListener */ public static FakeEventListener getCreate() { FakeEventListener listener = RequestCycle.get().getMetaData(DATA_KEY); if (listener == null) { listener = new FakeEventListener(); RequestCycle.get().setMetaData(DATA_KEY, listener); } return listener; } /** * Gets without create. * * @return {@link FakeEventListener} */ public static FakeEventListener get() { return RequestCycle.get().getMetaData(DATA_KEY); } } /** * */ package com.tustor.tuntinetti.view.reusables.components; import org.apache.wicket.AttributeModifier; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.IAjaxCallDecorator; import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior; import org.apache.wicket.behavior.AttributeAppender; import org.apache.wicket.markup.ComponentTag; import org.apache.wicket.markup.html.IHeaderContributor; import org.apache.wicket.markup.html.IHeaderResponse; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.Model; import org.apache.wicket.util.string.JavascriptUtils; import com.tustor.common.wicket.constants.JavaScriptConstants; import com.tustor.tuntinetti.view.reusables.components.FakeEventButton.FakeAjaxEventBehavior; /** * Fake event button which trigger fake event to parent. Parent need to have * {@link FakeAjaxEventBehavior} attached. * * */ public abstract class FakeAjaxFormComponentUpdatingBehavior extends AjaxFormComponentUpdatingBehavior implements IHeaderContributor { private static final String FAKE_EVENT_NAME = "fake"; private String parentMarkupId; private final boolean busySignal; private boolean isCollectString = false; /** * Construct. * * @param parentMarkupId * @param busySignal * @param isCollectString */ public FakeAjaxFormComponentUpdatingBehavior(String parentMarkupId, boolean busySignal, boolean isCollectString) { super("fake"); this.busySignal = busySignal; this.parentMarkupId = parentMarkupId; this.isCollectString = isCollectString; } /** * @see org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior#onBind() */ @Override protected void onBind() { super.onBind(); if (AjaxRequestTarget.get() != null) { getComponent().add(new AttributeAppender("class",true, new AbstractReadOnlyModel<String>() { /** * @see org.apache.wicket.model.AbstractReadOnlyModel#getObject() */ @SuppressWarnings("synthetic-access") @Override public String getObject() { if (FakeEventListener.get() == null) { AjaxRequestTarget.get().addListener(FakeEventListener.getCreate()); } return "FACB"+ FakeEventListener.get().index(FakeAjaxFormComponentUpdatingBehavior.this.parentMarkupId); } }, " ")); getComponent().add(new AttributeModifier("bs",true, Model.of(busySignal))); } } /** * * @param target */ public void fireOnEvent(AjaxRequestTarget target) { onEvent(target); } /** * @see org.apache.wicket.behavior.AbstractAjaxBehavior#onComponentRendered() */ @Override protected void onComponentRendered() { super.onComponentRendered(); String event = getEvent(); Component component = getComponent(); if(!isCollectScripts()) { onComponentRendered(event, component); } } /** * @see org.apache.wicket.ajax.AjaxEventBehavior#onComponentTag(org.apache.wicket.markup.ComponentTag) */ @Override protected void onComponentTag(ComponentTag tag) { if(!isCollectScripts()) { super.onComponentTag(tag); } } /** * @param event * @param component */ protected static void onComponentRendered(String event, Component component) { JavascriptUtils.writeOpenTag(component.getResponse()); component.getResponse().write("$('#" + component.getMarkupId() + "').change(function() { eval($(this).attr('" + event + "')); });"); JavascriptUtils.writeCloseTag(component.getResponse()); } /** * @return Should scripts be collected. */ protected final boolean isCollectScripts() { return isCollectString; } /** * @see org.apache.wicket.ajax.AbstractDefaultAjaxBehavior#renderHead(org.apache.wicket.markup.html.IHeaderResponse) */ @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); response.renderJavascriptReference(JavaScriptConstants.JS_JQUERY); if(isCollectScripts() && AjaxRequestTarget.get() != null) { response.renderJavascriptReference(FakeAjaxCheckBox.JS); if (FakeEventListener.get() == null) { AjaxRequestTarget.get().addListener(FakeEventListener.getCreate()); } FakeEventListener.get().addScript(parentMarkupId); } } /** * * @param target */ protected abstract void onUpdate(AjaxRequestTarget target); /** * * @return Click script. */ protected String getOnClickScript() { CharSequence onClickScript = "$('#" + parentMarkupId + "').trigger('" + FAKE_EVENT_NAME + "', '" + getComponent().getMarkupId() + "'); return " + busySignal + ";"; IAjaxCallDecorator decorator = getDecorator(); if (decorator != null) { onClickScript = decorator.decorateScript(onClickScript); } else if (AjaxRequestTarget.get() != null) { return null; } return onClickScript.toString(); } /** * Get decorator. Only {@link IAjaxCallDecorator#decorateScript(CharSequence)} * is used here! * * @return {@link IAjaxCallDecorator} */ protected IAjaxCallDecorator getDecorator() { return null; } /** * @return the parentMarkupId */ public String getParentMarkupId() { return parentMarkupId; } /** * @param parentMarkupId the parentMarkupId to set */ public void setParentMarkupId(String parentMarkupId) { this.parentMarkupId = parentMarkupId; } /** * @return the isCollectString */ public boolean isCollectString() { return isCollectString; } /** * @param isCollectString the isCollectString to set */ public void setCollectString(boolean isCollectString) { this.isCollectString = isCollectString; } /** * @return the busySignal */ public boolean isBusySignal() { return busySignal; } } ** Martin > On Jan 10, 2015 4:43 AM, "Martin Makundi" < > [email protected]> wrote: > > > Hi! > > > > I tried to add and idea to > > https://cwiki.apache.org/confluence/display/WICKET/Ideas+for+Wicket+7.0 > > > > However I cannot find any edit buttons when Logged in to confluence. The > > contribution page says anybody can contribute? > > > > My idea is related to "Better stateless support > > < > > > https://cwiki.apache.org/confluence/display/WICKET/Ideas+for+Wicket+7.0#IdeasforWicket7.0-Betterstatelesssupport > > > > > ": > > > > > > - Wicket seems to have this inherent MVC design flaw that it's View is > > stateful when it would really be sufficient that the Model is stateful > > and > > it does not (and neither does controller) need to be serialized. > > - It is possible to tweak to implement stateless View but it's quite a > > hack because most event listeners are attached to the hierarcy instead > > of > > page root which would have avoided the need to keep/serialize state of > > the > > view. We have prototypes of "FakeAjaxEventBehavior" which is bound to > > page > > instead of a component; the component event thus invokes the > page-level > > listener (on gui side) and thus in event processing (page level) we > > don't > > need the component itself nor its state. > > - Form components, however, are difficult to implement because they > > inherently have state in view, but on the other hand it is rare (and > > impractical) to actually have 'huge' forms; any such large editing > areas > > will need to be 'worked around' some another way. > > > > > > ** > > Martin > > >
