Skip to content


Wicket - No TransparentResolver

Wie ich im letzten Beitrag bereits angkündigt habe, kann man tatsächlich das TransparentResolver-Problem mit Hilfe der verzögerten Initialisierung lösen. Dazu muss die AbstractLazyPanel-Klasse nur ein wenig verändert werden.

package de.wicketpraxis.web.blog.pages.questions.transparent.lazy;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.markup.html.panel.Panel;

public abstract class AbstractLazyPanel extends Panel
{
  boolean _lazyInitCalled;
  
  public AbstractLazyPanel(String id)
  {
    super(id);
  }

  @Override
  protected void onBeforeRender()
  {
    if (!_lazyInitCalled)
    {
      _lazyInitCalled=true;
      lazyInit();
    }
    super.onBeforeRender();
  }

  protected abstract MarkupContainer lazyInit();
}

Die Methode lazyInit() liefert die Komponente zurück, unter der alle Kindkomponenten eingehangen werden müssen. Das sieht in eigenen Komponenten dann wie folgt aus:

package de.wicketpraxis.web.blog.pages.questions.transparent.lazy;

import org.apache.wicket.MarkupContainer;
import org.apache.wicket.markup.html.WebMarkupContainer;

public abstract class BasePanel extends AbstractLazyPanel
{
  public BasePanel(String id)
  {
    super(id);
  }

  @Override
  protected MarkupContainer lazyInit()
  {
    WebMarkupContainer border = new WebMarkupContainer("border");
    add(border);
    return border;
  }
}

Hier erstellen wir einen Container, den wir an ein div-Tag binden.

<wicket:panel>
  Base
  <div style="border:1px solid blue" wicket:id="border">
    <wicket:child />
  </div>
  Base End
</wicket:panel>

Die davon abgeleitete Klasse sieht dann wie folgt aus:

package de.wicketpraxis.web.blog.pages.questions.transparent.lazy;

import org.apache.wicket.MarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.Model;

public class SubPanel extends BasePanel
{
  public SubPanel(String id)
  {
    super(id);
  }

  @Override
  protected MarkupContainer lazyInit()
  {
    MarkupContainer root = super.lazyInit();
    root.add(new Label("label",Model.of("Sub")));
    return root;
  }
}
<wicket:extend>
  <span wicket:id="label"></span>
</wicket:extend>

Wie man sehen kann, wurde in diesem Beispiel sowohl Markup- als auch Komponentenvererbung benutzt. Trotzdem konnte auf den Einsatz von TransparentResolver verzichtet werden. Die Komponentenhierarchie entspricht der im Markup.

Ich hätte nicht gedacht, dass die Lösung so nahe liegt. Feedback wie immer willkommen...

Tags:

Veröffentlicht in Allgemein, Refactoring, Wicket, .

Wicket - verzögerte Initialisierung

Nicht immer ist es möglich oder sinnvoll, im Konstruktor einer Komponente bereits die vollständige Komponentenstruktur anzulegen. Wie man Komponenten zu einem späteren Zeitpunkt anlegen kann, kann man in den Repeater-Klassen ansehen. Aber es geht wesentlich einfacher. Nach dem Erstellen einer Komponente wird als nächstes (für den Fall,dass die Komponente dargestellt wird) onBeforeRender() aufgerufen. Wir können die fehlenden Komponenten in diesem Methodenaufruf erstellen. Wir müssen nur darauf achten, dass diese Initialisierung nur einmal durchgeführt wird. Am besten verpacken wir das ganze in eine eigene Klasse.

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

import org.apache.wicket.markup.html.panel.Panel;

public abstract class AbstractLazyPanel extends Panel
{
  boolean _lazyInitCalled;
  
  public AbstractLazyPanel(String id)
  {
    super(id);
  }

  @Override
  protected void onBeforeRender()
  {
    if (!_lazyInitCalled)
    {
      _lazyInitCalled=true;
      lazyInit();
    }
    super.onBeforeRender();
  }

  protected abstract void lazyInit();
}

Eigene Komponenten werden dann von dieser Klasse abgeleitet. Dieser Umbau hat keine Veränderung des Markup zur Folge, da keinerlei Hilfskomponenten eingefügt wurden.

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

import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.Model;

public class TestPanel extends AbstractLazyPanel
{
  public TestPanel(String id)
  {
    super(id);
  }

  @Override
  protected void lazyInit()
  {
    add(new Label("label",Model.of("Label")));
    add(new SimplePanel("panel"));
  }
}
<wicket:panel>
  <span wicket:id="label"></span>
  <br>
  <wicket:container wicket:id="panel"></wicket:container>
</wicket:panel>

Wie man sieht, lässt sich die neuen Klasse sehr einfach als Ersatz für die Panel-Klasse benutzen. Vielleicht ist dieser Ansatz ausbaufähig, so dass man durch eine verspätete Initialisierung auch die Probleme rund um TransparentResolver umgehen kann.

Tags:

Veröffentlicht in Allgemein, Refactoring, Wicket, .