在向JSF组件树动态添加新组件时重复id

时间:2012-12-03 15:26:41

标签: jsf dynamic primefaces components mojarra

使用JSF 2.1,Mojarra 2.1.3,Glassfish 3.1.1和PrimeFaces 3.3.1

我正在尝试在preRenderView事件中处理JSF中的处理字段级安全性,并且在需要向JSF组件树添加动态组件时遇到问题。在第一次渲染时,一切都很好,并处理字段级安全性。然而,在任何类型的更新之后,Mojarra抱怨重复的ID,即使通过打印到控制台,我的添加代码每次更新只运行一次。

似乎Mojarra没有清除回发组件树,因此每次后续渲染的更新都会向树中添加一个额外版本的组件。

感谢任何人提供的任何帮助。这是一些愚蠢的示例代码。在commandButton上单击引发的错误。

的index.xhtml:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:p="http://primefaces.org/ui"
        >
    <f:event listener="#{lifeCycle.event}" type="preRenderView" />
    <h:body>
        <h:form id="form" prependId="false">
            <h:panelGroup id="testPanel">
                <h:inputText id="viewSec" value="viewSec node"/><br/>
            </h:panelGroup>
            <p:commandButton update="testPanel"/>
        </h:form>
    </h:body>
</html>

LifeCycle.java:

package com.dynamic.test;

import java.io.Serializable;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlOutputText;
import javax.faces.component.visit.VisitContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;

@ManagedBean
@RequestScoped
public class LifeCycle implements Serializable {
    public void event(ComponentSystemEvent event){
        FacesContext facesContext = FacesContext.getCurrentInstance();
        UIViewRoot root = facesContext.getViewRoot();
        NodeInspector visitCallback = new NodeInspector();

        root.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()), visitCallback);

        List<UIComponent> securityEnabledComponents = visitCallback.getSecurityEnabledComponents();
        for (UIComponent securityEnabledComponent : securityEnabledComponents) {

            if(securityEnabledComponent.getClientId().equals("viewSec")){
                List<UIComponent> childList = securityEnabledComponent.getParent().getChildren();
                int targetPosition = securityEnabledComponent.getParent().getChildren().indexOf(securityEnabledComponent);

                HtmlOutputText outputTextComponent = new HtmlOutputText();
                outputTextComponent.setId(securityEnabledComponent.getId());
                outputTextComponent.setValue(securityEnabledComponent.getAttributes().get("value"));

                childList.set(targetPosition, outputTextComponent);
            }
        }
    }
}

NodeInspector.java

package com.dynamic.test;

import java.util.ArrayList;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;

public class NodeInspector implements VisitCallback {
    private List<UIComponent> securityEnabledComponents = new ArrayList<UIComponent>();
    FacesContext facesContext = FacesContext.getCurrentInstance();

    @Override
    public VisitResult visit(final VisitContext context, final UIComponent target) {
        if(target.getClientId().equals("viewSec")){
            securityEnabledComponents.add(target);
        }
        return VisitResult.ACCEPT;
    }

    public List<UIComponent> getSecurityEnabledComponents() {
        return securityEnabledComponents;
    }
}

错误:

SEVERE: JSF1007: Duplicate component ID viewSec found in view.
    ...  +id: j_idt2
       type: <html xmlns="http://www.w3.org/1999/xhtml">

      +id: j_idt3
       type: javax.faces.component.UIOutput@17098e7
        +id: form
         type: javax.faces.component.html.HtmlForm@14677de
          +id: testPanel
           type: javax.faces.component.html.HtmlPanelGroup@167ab25
            +id: viewSec  <===============
             type: javax.faces.component.html.HtmlOutputText@14a3d2e
            +id: viewSec  <===============
             type: javax.faces.component.html.HtmlOutputText@f6a607
            +id: j_idt4
             type: <br/>

          +id: j_idt5
           type: org.primefaces.component.commandbutton.CommandButton@1380fc5
      +id: j_idt6
       type: 
    </html>...

    SEVERE: Error Rendering View[/index.xhtml]
    java.lang.IllegalStateException: Component ID viewSec has already been found in the view.  
        at com.sun.faces.util.Util.checkIdUniqueness(Util.java:821)...

1 个答案:

答案 0 :(得分:-1)

检查您使用的Mojarra版本是否与Primefaces 3.3.1兼容。
使用最新版本的Primefaces 3.6。