Как добавить существующие компоненты 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 делает под капотом, или, как кажется, просматривая исходный код:)