Как добавить существующие компоненты JSF в мои собственные компоненты?

У меня есть класс тегов, который расширяет UIComponent и UIOutput. В этом классе у меня есть encodeBegin и encodeEnd, которые я могу использовать с помощью contextWriter для вывода любого html-тега своего рода, который я тоже хочу, используя writer.startElement("div", myComponent) и так далее.

Моя проблема сейчас в том, что мне нужно вставить, например, вместо использования writer.startElement. Я могу сделать это, выполнив getChildren(). Add(HtmlCommandButton button = new HtmlCommandButton()); но при этом я не могу вывести компонент там, где я хочу, чтобы он появлялся, как я могу с write.startElement.

Есть ли у кого-нибудь хорошие решения в том, как я могу использовать теги richfaces, JSF-теги и аналогичные в моей собственной библиотеке тегов? Короче говоря, то, что я действительно хотел бы сделать, находится внутри моего encodeBegin:

writer.startElement("a4j:commandButton", myComponent);
writer.writeAttribite("action", "#{Handler.myAction}", null);
writer.endElement("a4j:commandButton");

Заранее спасибо

2 ответа

Решение

Вы не можете использовать ResponseWriter так, как хотите. Два способа, которыми я могу думать о том, как добавить дочерние элементы управления программно, - либо через атрибут связывания ( см. Этот ответ), либо в месте, где обычно создаются элементы управления (в JSP, то есть в классе тегов).

У компонентов JSF есть два способа содержать другие элементы управления: как дочерние или как именованные фасеты. Компоненты всегда контролируют, как они отображают свои фасеты; если они должны отобразить своих детей, они должны вернуть true для getRendersChildren.

Это непроверенный код, но последовательность выглядит примерно так:

  @Override
  public boolean getRendersChildren() {
    return true;
  }

  @Override
  public void encodeBegin(FacesContext context)
      throws IOException {
    // should really delegate to a renderer, but this is only demo code
    ResponseWriter writer = context.getResponseWriter();
    writer.startElement("span", this);
    String styleClass = getStyleClass();
    writer
        .writeAttribute("class", styleClass, "styleClass");

    UIComponent headerComponent = getFacet("header");
    if (headerComponent != null) {
      headerComponent.encodeAll(context);
    }

    writer.startElement("hr", null);
  }

  @Override
  public void encodeChildren(FacesContext context)
      throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    for (UIComponent kid : getChildren()) {
      kid.encodeAll(context);
      writer.startElement("br", null);
    }
  }

  @Override
  public void encodeEnd(FacesContext context)
      throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    writer.endElement("span");
  }

Не совсем ответ, скорее предположение, но, может быть, вы могли бы расширить один из элементов управления Facelets?

В качестве альтернативы, либо используйте Facelets напрямую - что, кажется, именно то, что вы действительно хотите, хотя я сам не использовал его. Или вы можете добавить элементы управления UIOutput, где вы хотите, чтобы HTML отображался, и установить значение каждого из них в HTML, который вы хотите отобразить - это именно то, что f:verbatim делает под капотом, или, как кажется, просматривая исходный код:)

Другие вопросы по тегам