package de.flower.common.ui.ajax.event; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.behavior.Behavior; import org.apache.wicket.event.IEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Attach this behavior to any component that wants to be added to an ajaxRequestTarget on certain events. */ public final class AjaxEventListener extends Behavior { private final static Logger log = LoggerFactory.getLogger(AjaxEventListener.class); /** * Events that this behavior listens for. */ private final Object[] registeredEvents; /** * Instantiates a new ajax update behavior. * * @param eventObjects event (or event list) that the component wants to listen on. Events are matched by using {@link #equals(Object)}. */ public AjaxEventListener(final Object... registeredEvents) { this.registeredEvents = registeredEvents; } /** * Called immediately after attaching the behavior. Helps to make the constructor leaner. * * @param component the component */ @Override public void bind(final Component component) { // ajax updates always require that the component has markupId set to true. component.setOutputMarkupId(true); } @Override public void onEvent(final Component component, final IEvent<?> event) { super.onEvent(component, event); final Object payload = event.getPayload(); if (!isAjaxEventPayload(payload)) { return; } if (checkForComponentUpdate(payload)) { // add to ajax request target final AjaxRequestTarget target = AjaxRequestTarget.get(); if (target != null) { // detach models so that component loads fresh data when it is repainted. component.detach(); // components that are not visible and don't have outputmarkupplaceholder cannot be // updated. if (component.isVisibleInHierarchy() || (component.getParent().isVisibleInHierarchy() && component.getOutputMarkupPlaceholderTag())) { target.add(component); } else { // downgrad log level to info to avoid RMT-720. log.info("Cannot add component [{}] to ajax request target. Component or parent is not visible.", component); } } } } // NOTE (oliverb - 13.10.2011): implement this method if typed payloads are to be used. @SuppressWarnings("SameReturnValue") private boolean isAjaxEventPayload(final Object payload) { // return (payload instanceof AjaxEvent); return true; } /** * Determine if component needs to be updated (or added to ajaxRequestTarget). * Does any of the event objects match one of this.registeredEvents? * * @param triggeredEvent the triggered event * @return true, if component should be added to ajax request target. */ // NOTE (oliverb - 13.10.2011): think about strongly typing the payload, e.g. as an AjaxEvent. public boolean checkForComponentUpdate(final Object triggeredEvent) { for (final Object registeredEvent : registeredEvents) { if (registeredEvent.equals(triggeredEvent)) { return true; } } return false; } }