I want to create custom component which adds new child to page "head" facet.
This custom component is based on h:selectOneMenu. When used on jsf page, user can simply change the current theme. What I need this component to do is to add stylesheet child to head facet.
My component has backing java. I trie开发者_Python百科d to modify "head" in encodeBegins() method, but my child is not rendered at all. Take a look at the implementation:
@FacesComponent(value = "com.ramps.util.ThemeSelector")
public class ThemeSelector extends UIInput implements NamingContainer {
public void encodeBegin(FacesContext context) throws IOException {
UIComponent headFacet = context.getViewRoot().getFacet("javax_faces_location_HEAD");
Resource res = new Resource();
res.setName("...");
...
List <UIComponent> headChildren = headFacet.getChildren();
headChildren.add(res);
super.encodeBegin(context);
}
}
Is it possible to modify "head" facet directly from backing java of my custom component? If so, what am I missing?
RegardsUIViewRoot has a method to add a resource component to the head target of the view:
public void addComponentResource(FacesContext context, UIComponent componentResource): Add componentResource, that is assumed to represent a resource instance, to the current view. A resource instance is rendered by a resource Renderer (such as ScriptRenderer, StylesheetRenderer) as described in the Standard HTML RenderKit. This method will cause the resource to be rendered in the “head” element of the view.
For your case, the component is an UIOutput with an attribute name and a render type of javax.faces.resource.Stylesheet.
You can add the stylesheet resource after your custom component is added to the view. You make this, registering it for listening to PostAddToViewEvent's. The UIInput already implements ComponentSystemEventListener so you have to override processEvent.
This is a working example of a component that adds a stylesheet.
@FacesComponent("CustomComponent")
@ListenerFor(systemEventClass=PostAddToViewEvent.class)
public class CustomComponent extends UIInput{
@Override
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
if(event instanceof PostAddToViewEvent){
UIOutput resource=new UIOutput();
resource.getAttributes().put("name", "theme.css");
resource.setRendererType("javax.faces.resource.Stylesheet");
FacesContext.getCurrentInstance().getViewRoot().addComponentResource(FacesContext.getCurrentInstance(), resource);
}
super.processEvent(event);
}
}
I wonder if using a composite component is not easier for what you are trying to do.
精彩评论