3

我想创建自定义组件,将新子组件添加到页面“head”方面。

此自定义组件基于 h:selectOneMenu。在 jsf 页面上使用时,用户可以简单地更改当前主题。我需要这个组件做的是将样式表子添加到 head facet。

我的组件支持 java。我试图在 encodeBegins() 方法中修改“head”,但我的孩子根本没有渲染。看一下实现:



@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);
  }
 }

是否可以直接从我的自定义组件的支持 java 修改“head”方面?如果是这样,我错过了什么?
问候

4

1 回答 1

4

UIViewRoot 有一个方法可以将资源组件添加到视图的头部目标:

public void addComponentResource(FacesContext context, UIComponent componentResource): 将componentResource(假定代表资源实例)添加到当前视图。资源实例由资源渲染器(例如 ScriptRenderer、StylesheetRenderer)渲染,如标准 HTML RenderKit 中所述。此方法将导致资源在视图的“head”元素中呈现。

对于您的情况,该组件是一个 UIOutput ,其属性名称和渲染类型为javax.faces.resource.Stylesheet

您可以在将自定义组件添加到视图后添加样式表资源。你做了这个,注册它来监听 PostAddToViewEvent。UIInput 已经实现了 ComponentSystemEventListener,所以你必须重写 processEvent。

这是一个添加样式表的组件的工作示例。

@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);
    }

}

我想知道使用复合组件是否对您尝试做的事情并不容易。

于 2011-02-07T09:46:47.577 回答