Come aggiungere componenti JSF esistenti ai miei componenti personalizzati?
-
19-08-2019 - |
Domanda
Ho una classe di tag che estende UIComponent e UIOutput. In questa classe ho encodeBegin e encodeEnd che posso usare il mio contextWriter per generare qualsiasi tipo di tag html che voglio anche usando writer.startElement (" div " ;, myComponent) e così via.
Il mio problema ora è che devo inserire ad esempio un invece di usare writer.startElement. Posso farlo facendo getChildren (). Add (HtmlCommandButton button = new HtmlCommandButton ()); ma quando lo faccio in questo modo non riesco a visualizzare il componente dove voglio che appaiano, come posso con write.startElement.
Qualcuno ha delle buone soluzioni su come sfruttare i tag richfaces, i tag JSF e simili nel mio tagliobrary? In breve, ciò che vorrei davvero fare è all'interno del mio encodeBegin:
writer.startElement("a4j:commandButton", myComponent);
writer.writeAttribite("action", "#{Handler.myAction}", null);
writer.endElement("a4j:commandButton");
Grazie in anticipo
Soluzione
Non puoi usare ResponseWriter come desideri. Due modi in cui posso pensare a come aggiungere controlli figlio a livello di codice sono tramite l'attributo binding ( vedi questa risposta ) o nel luogo in cui i controlli vengono generalmente creati (in JSP, ovvero in tag class ).
Esistono due modi in cui i componenti JSF possono contenere altri controlli: come figli o come facet con nome. I componenti controllano sempre il modo in cui rendono le loro sfaccettature; se vogliono rendere i propri figli, devono restituire true per getRendersChildren .
Questo è un codice non testato, ma la sequenza è simile a questa:
@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");
}
Altri suggerimenti
Non proprio una risposta, più un'ipotesi, ma forse potresti estendere uno dei controlli delle facce?
In alternativa, usa direttamente le faccette - che sembra essere esattamente quello che vuoi davvero anche se non l'ho usato da solo. Oppure potresti aggiungere i controlli UIOutput dove vuoi che appaia l'HTML e impostare il valore di ciascuno sull'HTML che vuoi che appaia - questo è esattamente ciò che f: verbatim fa sotto il cofano, o almeno così sembra guardando il codice sorgente: - )