您可以在
PreRenderViewEvent期间操作组件树.在此期间,所有组件都保证存在于树中,并且通过在树中添加/移动/移除组件来保证操作组件树是安全的.您可以在
UIComponent#findComponent()中找到树中的其他组件.您可以使用
UIComponent#getParent()和
UIComponent#getChildren()遍历组件树.getChildren()返回一个可变列表,保证在PreRenderViewEvent期间可以安全操作.
鉴于您希望使用超链接包装给定组件,并且已经存在JSF超链接组件< h:outputLink>,则更容易扩展和重用它以保持代码简单和干燥.这是一个基本的启动示例:
@FacesComponent(createTag=true)
public class Banana extends HtmlOutputLink implements SystemEventListener {
public Banana() {
getFacesContext().getViewRoot().subscribeToViewEvent(PreRenderViewEvent.class,this);
}
@Override
public boolean isListenerForSource(Object source) {
return source instanceof UIViewRoot;
}
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
String forClientId = (String) getAttributes().get("for");
if (forClientId != null) {
UIComponent forComponent = findComponent(forClientId);
List forComponentSiblings = forComponent.getParent().getChildren();
int originalPosition = forComponentSiblings.indexOf(forComponent);
forComponentSiblings.add(originalPosition,this);
getChildren().add(forComponent);
}
}
}
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:my="http://xmlns.jcp.org/jsf/component"
>
SO question 38197494请注意,当您已经执行children.add()时,不需要显式的children.remove()调用.它会自动照顾孩子的父母.