Reputation: 61
i'm trying to get a better grasp of JSF2 internals by writing a small "tree" component, that takes a node-Structure and renders it into simple ul/li elements.
It should be possible to define the Way, the content of a leaf is rendered somewhat like this (similar to h:DataTable):
<custom:tree value="#{someBean.someListProperty}" var="nodeData">
<h:outputText value="#{nodeData}" />
...
</custom:tree>
Currently i'm struggling to figure out, how to "populate" that variable into the current context. I tried something like this, but it didn't work:
@Override
@SuppressWarnings("unchecked")
public void encodeChildren(FacesContext context) throws IOException {
if ((context == null)){
throw new NullPointerException();
}
ArrayList<String> list = (ArrayList<String>) getStateHelper().eval("value");
String varname = (String) getStateHelper().eval("var");
if(list != null){
for(String str : list){
getStateHelper().put(varname, str);
for(UIComponent child: getChildren()){
child.encodeAll(context);
}
}
}
}
For simplification i first started to use a simple ArrayList of Strings and print out the contents iteratively. Here is the xhtml:
<custom:tree value="#{testBean.strings}" var="testdata">
<h:outputText value="#{testdata}" />
</custom:tree>
So, what would be the correct way to achieve this?
Best regards, Christian Voß
Upvotes: 1
Views: 936
Reputation: 61
Thanks BalusC,
to keep it simple, this is basically the (or better one possible) answer to my question:
You can put a new variable under the given key into the requestMap and any child component will be able to access it, using the specified ValueExpression.
@Override
@SuppressWarnings("unchecked")
public void encodeChildren(FacesContext context) throws IOException {
if ((context == null)){
throw new NullPointerException();
}
ArrayList<String> list = (ArrayList<String>) getStateHelper().eval("value");
String varname = (String) getStateHelper().eval("var");
Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
varStore = requestMap.get(varname); // in case this Object already exists in the requestMap,
// emulate "scoped behavior" by storing the value and
// restoring it after all rendering is done.
if(list != null){
for(String str : list){
requestMap.put(varname, str);
for(UIComponent child: getChildren()){
child.encodeAll(context);
}
}
// restore the original value
if(varStore != null){
requestMap.put(varname, varStore);
}else{
requestMap.remove(varname);
}
}
}
Upvotes: 2