Como adicionar componentes JSF existentes para meus próprios componentes personalizados?
-
19-08-2019 - |
Pergunta
Eu tenho uma classe tag que se estende UIComponent e UIOutput. Nesta classe eu tenho encodeBegin e encodeEnd que posso usar meu contextWriter a saída de qualquer tag meio html eu quero também usando writer.startElement ( "div", myComponent) e assim por diante.
O meu problema agora é que eu preciso inserir, por exemplo, uma vez de usar o writer.startElement. Eu posso conseguir este feito, fazendo getChildren () adicionar (botão HtmlCommandButton = new HtmlCommandButton ()).; mas ao fazê-lo gosto que eu não posso parecer para a saída do componente onde eu quero que eles apareçam, como eu posso com write.startElement.
Alguém tem alguma boas soluções em como posso tirar proveito de richfaces etiquetas, tags JSF e similar em minha própria taglibrary? Em suma o que eu realmente quero fazer é dentro da minha encodeBegin:
writer.startElement("a4j:commandButton", myComponent);
writer.writeAttribite("action", "#{Handler.myAction}", null);
writer.endElement("a4j:commandButton");
Graças por antecedência
Solução
Você não pode usar o ResponseWriter como você deseja. Duas maneiras que eu posso pensar de como adicionar controles filho de programação são ou através do obrigatório atributo ( veja esta resposta ) ou no lugar onde os controles normalmente são criados (em JSPs, que está no class tag ).
Existem duas maneiras para componentes JSF para conter outros controles: como crianças ou como facetas nomeados. Componentes sempre controlar como eles processam as suas facetas; se eles estão a tornar seus filhos, eles devem retornar verdadeiro para getRendersChildren .
Este é o código não foi testado, mas a seqüência é algo como isto:
@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");
}
Outras dicas
Não é realmente uma resposta, mais de um palpite, mas talvez você poderia estender um dos controles facelets?
Como alternativa, use facelets diretamente - o que parece ser exatamente o que você quer realmente que eu não usei-me. Ou você pode adicionar controles UIOutput onde você quer HTML para aparecer e definir o valor de cada um para o HTML você quer que apareça - este é exatamente o que f: verbatim faz sob o capô, ou assim parece de olhar para o código-fonte: - )