Калитка "обнуляемый" вид компонента - PullRequest
3 голосов
/ 03 февраля 2012

Довольно часто я использую пользовательские компоненты Wicket для рендеринга объектов модели.Объекты могут иногда быть нулевыми, в этом случае отображается определенный div.В коде рендеринга компонента HTML, таким образом, у меня есть два элемента div, один для случая «null» и один для случая «non-null», с другой внутренней разметкой.Один отображается, в то время как другой маскируется.

<div wicket:id="toDisplayWhenObjectIsNull">
    ...
</div>
<div wicket:id="toDisplayWhenObjectIsNotNull">
   <span wicket:id="label">...</span>
   <table wicket:id="table">...</table>
   ...
</div>

Проблема, с которой я сталкиваюсь, заключается в том, что Wicket заставляет меня полностью построить два div, даже если объект модели нулевой.Во всех вызовах к построению подкомпонентов (метки, таблицы и т. Д.) Я должен проверять на нулевое значение, что является громоздким и подверженным ошибкам:

X myX = getModel().getModelObject();
Label label = new Label("label",
    myX == null ? null : formatY(myX.getY()));

Первое решение этого было быразделить ненулевую часть на определенный подкомпонент калитки, либо как собственный класс, либо как внутренний класс главного компонента;и вставив этот компонент вместо "ненулевого" div.Но это удваивает количество необходимых файлов (ресурсы, HTML, код Java).Это не идеально.

Второе решение, универсальное, состояло бы в том, чтобы создать компонент «декоратор» для инкапсуляции любого другого компонента и проверки на нулевое значение в его объекте модели.Если компонент имеет значение null, он будет отображать стандартный div, а если нет, он будет полагаться на декорированный компонент.Я пытался реализовать это с помощью рамок или составных панелей, но мне не удалось заставить его работать.Я хотел бы добиться чего-то вроде этого:

// Client code, Java
ViewXPanel xpanel = new ViewXPanel("xpanel", new Model<X>(x));
add(xpanel);

// HTML
<div wicket:id="xpanel"/>

ИЛИ, если необходимо, возложить на клиента ответственность за «обнуляемость» отображаемого компонента, используя что-то вроде этого в коде клиента:

// Client code, Java
ViewXPanel xpanel = new NullableDecorator(?, ViewXPanel(...));
add(xpanel);

Ответы [ 3 ]

0 голосов
/ 06 февраля 2012

Вы не используете рекомендуемые шаблоны калиток: (.

Вместо того, чтобы что-то вытаскивать из модели и вставлять в другой компонент:

X myX = getModel().getModelObject();
Label label = new Label("label", myX == null ? null : formatY(myX.getY()));

... используйте модели правильно:

Label label = new Label("label", new AbstractReadonlyModel<Y>() {
    public Y getObject() {
        return formatY(getModel().getModelObject().getY());
    }
});

Всегда делай так.

Нет необходимости проверять нулевое значение, кроме переключения между «toDisplayWhenObjectIsNull» и «toDisplayWhenObjectIsNotNull» на верхнем уровне иерархии компонентов.

0 голосов
/ 22 июня 2016

То, что я сделал для того, чтобы иметь возможность отображать нулевые значения, было то, что я создал свой собственный подкласс Label, в котором я переопределяю onComponentTagBody(), чтобы заменить пустую строку заполнителем:

/**
 * Since the converter is not invoked for null values, override this so that 
 * empty string can be replaced with null display value.
 */
@Override
public void onComponentTagBody(MarkupStream markupStream, ComponentTag openTag)
{
    String value = getDefaultModelObjectAsString();
    replaceComponentTagBody(markupStream, openTag, 
                            value.isEmpty()? "N/A": value);
}

Этопозволит использовать

// Client code, Java
add(new MyLabel("label");

// HTML
<div wicket:id="label"/>

Вам, конечно, придется настраивать свои предпочтения по локализации и тому подобное, но я надеюсь, что вы получите общую картину из предоставленного примера.

0 голосов
/ 04 февраля 2012

Что ж, один обходной путь - эффективное использование фрагментов, как предлагает biziclop, поэтому я описываю его здесь для справки, но не отмечаю его как «ответ».

ViewX.html:

<wicket:panel ...>
  <div wicket:id="mainPanel"></div>
  <wicket:fragment wicket:id="nullFragment">
    ...markup for NULL case...
  </wicket:fragment>
  <wicket:fragment wicket:id="nonNullFragment">
    <h4><span wicket:id="theName"></span></h4>
    ...other markup for non-NULL case...
  </wicket:fragment>
</wicket:panel

ViewX.java:

public class ViewX extends Panel {
  public ViewX(String id, IModel<X> xmodel) {
    if (x == null) {
      Fragment nullFragment = new Fragment("mainPanel", "nullFragment", null);
      ... eventual markup if needed ...
      add(nullFragment);
    } else {
      Fragment nonNullFragment = new Fragment("mainPanel", "nonNullFragment", null);
      nonNullFragment.add(new Label("theName", new PropertyModel(xmodel, "name")));
      ... other markup ...
      add(nonNullFragment);
} } }

Я все еще ищу действительно общее решение для этого, либо по композиции, наследованию или оформлению на панели ViewX, не поддерживающей нуль.

...