Skip to content


Wicket - AbstractEvent Update

Wie ich bereits beschrieben habe, kann man mit Wicket relativ leicht eine lose Koppelung von Komponenten über einen Event-Mechanismus erreichen. Dabei wurden bisher nur Komponenten berücksichtigt. Manchmal ist es aber sinnvoll, die Behandlung dieser Events an einer zentralen Stelle durchzuführen. Daher habe ich die Basisklasse leicht erweitert. Dabei ist der Visitior in eine eigene Klasse gewandert. Außerdem ist es wesentlich geschickter, auch bei nicht Ajax-Requests mit Events zu arbeiten. Die Modifikation des EventListener-Interface trägt dem Rechnung.

package de.wicketpraxis.web.blog.pages.questions.events;

public interface EventListenerInterface
{
  public void notifyEvent(AbstractEvent event);
}

Die Methode lautet nun notifyEvent statt notifyAjaxEvent .

package de.wicketpraxis.web.blog.pages.questions.events;

import org.apache.wicket.Component;
import org.apache.wicket.Component.IVisitor;

public class NotifyVisitor implements IVisitor<Component> 
{
  private final AbstractEvent _event;
   
  public NotifyVisitor(final AbstractEvent event)
  {
    _event = event;
  }
   
  public Object component(final Component component)
  {
    if (component instanceof EventListenerInterface) 
    {
      ((EventListenerInterface) component).notifyEvent(_event);
    }
    return IVisitor.CONTINUE_TRAVERSAL;
  }
}

Der Event sucht jetzt nicht nur in allen Komponenten nach dem EventListenerInterface, sondern auch in der Application, der Session und der Page.

package de.wicketpraxis.web.blog.pages.questions.events;

import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.Page;
import org.apache.wicket.Session;
import org.apache.wicket.Component.IVisitor;
import org.apache.wicket.ajax.AjaxRequestTarget;

public class AbstractEvent
{
  private final Component _source;
  protected final AjaxRequestTarget _target;
  
  public AbstractEvent(final Component source, AjaxRequestTarget target)
  {
    _source = source;
    _target = target;
  }
  
  public AbstractEvent(final Component source)
  {
    this(source,null);
  }
  
  public Component getSource()
  {
    return _source;
  }
  
  /**
   * notify Application, Session, Page and Components
   */
  public final void fire()
  {
    Page page=getSource().getPage();
    
    Application application=page.getApplication();
    if (application instanceof EventListenerInterface)
    {
      ((EventListenerInterface) application).notifyEvent(this);
    }
    Session session=page.getSession();
    if (session instanceof EventListenerInterface)
    {
      ((EventListenerInterface) session).notifyEvent(this);
    }
    if (page instanceof EventListenerInterface)
    {
      ((EventListenerInterface) page).notifyEvent(this);
    }
    page.visitChildren(EventListenerInterface.class, getVisitor());
    onAfterFire();
  }

  protected  void onAfterFire()
  {
    
  }

  protected IVisitor<Component> getVisitor()
  {
    return new NotifyVisitor(this);
  }

  public AjaxRequestTarget getTarget()
  {
    return _target;
  }
  
  public boolean isAjax()
  {
    return _target!=null;
  }

  public final void update(Component component)
  {
    if (_target!=null)
    {
      _target.addComponent(component);
    }
  }

}

Hinzugekommen ist außerdem die Funktion onAfterFire() die aufgerufen wird, sobald alle möglichen Listener benachrichtig wurden. An dieser Stelle könnte man dann Prüfungen einbauen, ob z.B. der Event überhaupt ein Ziel erreicht hat.

Ich glaube, dass diese Lösung zu offensichtlich war, so dass man sie leicht übersehen konnte.

Tags:

Veröffentlicht in Wicket, .