【问题标题】:PrimeFaces dynamic menu: Cannot remove the same component twice and ID generationPrimeFaces 动态菜单:不能两次移除同一个组件并生成 ID
【发布时间】:2016-06-28 16:00:05
【问题描述】:

我在 <p:dataTable> 中有一个 <p:menu>,在升级到 Mojarra 2.1.22(在 GlassFish 3.1.2.2 上)时,FacesExceptions 变得不规则:

        <p:dataTable id="data"
                     widgetVar="resultDataTable" 
                     value="#{depotManager.dataModel}"
                     var="dep"
                     rowKey="#{dep.id}"
                     selection="#{depotManager.selectedEntities}"
                     selectionMode="#{depotManager.singleSelectionMode ? 'single' : 'multiple'}"
                     ...
                     emptyMessage="#{msg['entity.depot.list.emptyMessage']}">

            <p:ajax event="rowSelect"...

            <f:facet name="header">
                <h:panelGroup id="header"
                              layout="block">

                    <p:menu overlay="true"
                            trigger="sub-client-button"
                            my="left top"
                            at="left bottom"
                            model="#{accountManagerMenuKeeper.subClientMenuModel}" />

我们得到的异常是:

javax.faces.FacesException: Cannot remove the same component twice: content-form:data:menu-item-1

类似的问题在这里:http://forum.primefaces.org/viewtopic.php?f=3&t=23669

我做了一些调查,问题似乎是我们在 PrimeFaces 3.5.28 中使用视图范围的 bean。我将菜单 bean 切换到请求范围,如下所述:

http://blog.primefaces.org/?p=2594

我们无法切换到 PrimeFaces 4... 一些异常消失了,但不是全部(可能是一半)。所以问题依然存在。

现在通过生成唯一 ID 更好地理解了这个问题,阅读 https://java.net/jira/browse/JAVASERVERFACES-2283 ,我可能需要在 dataTable 命名容器下生成 ID。

dataTable 的 ID 是“content-form:data”,所以我想我需要为每个动态菜单项生成唯一的 ID,我认为我目前没有这样做(每个客户端一个菜单项,附加简单计数器):

        for ( Client subClient : subClients )
        {
            MenuItem item = new MenuItem();
            item.setId( "menu-item-" + ( ++i ) );
//            item.setId( "content-form:data:menu-item-" + ( ++i ) );
            ...
        }

问:

如何在此处生成正确的 ID,例如使用 JSF 的内置方法,如 createUniqueId() 等?

这对我来说有点奇怪,因为异常提到了前面有 dataTable 的 ID 的完整 ID:javax.faces.FacesException: Cannot remove the same component twice: content-form:data:menu-item-1...

【问题讨论】:

    标签: jsf jsf-2 primefaces


    【解决方案1】:

    即使在 PrimeFaces 3.5.28 上使用简单的请求范围的菜单创建 bean,问题也消失了:

    @Named
    @RequestScoped
    public class AccountManagerMenuKeeper implements Serializable
    {
        private static final long serialVersionUID = 1L;
    
        @Inject
        @SeamLogger
        protected Logger          log;
    
        @Inject
        protected SessionHelper   sessionHelper;
    
        @Inject
        private DepotManager      accountManager;
    
        private MenuModel         subClientMenuModel;
    
        /**
         * @return the subClientMenuModel
         */
        public MenuModel getSubClientMenuModel()
        {
            if ( this.subClientMenuModel == null )
            {
                buildSubClientMenuModel();
            }
    
            return ( this.subClientMenuModel );
        }
    
        /**
         * Builds the menu model for adding sub-clients.
         * 
         */
        private void buildSubClientMenuModel()
        {
            this.subClientMenuModel = new DefaultMenuModel();
            List<Client> subClients = this.accountManager.getWritableSubClients();
    
            if ( subClients == null || subClients.isEmpty() )
                return;
    
            // Necessary instances
            FacesContext facesContext = FacesContext.getCurrentInstance();
            ELContext elContext = facesContext.getELContext();
            Application application = facesContext.getApplication();
            ExpressionFactory factory = application.getExpressionFactory();
    
            int i = 0;
    
            for ( Client subClient : subClients )
            {
                MenuItem item = new MenuItem();
                item.setId( "menu-item-" + ( ++i ) );
    
                item.setValue( subClient.getName() );
                item.setProcess( "@this" );
                item.setUpdate( ":content-form" );
                item.setDisabled( this.accountManager.isReadOnly() || !this.accountManager.isSingleSelectionMode() || EMode.ADD.equals( this.accountManager.getMode() ) || EMode.EDIT.equals( this.accountManager.getMode() ) );
                item.setActionExpression( factory.createMethodExpression( elContext, "#{depotManager.add}", String.class, new Class[] {} ) );
    
                ValueExpression targetExpression = factory.createValueExpression( elContext, "#{depotManager.selectedSubClientId}", Long.class );
                ValueExpression valueExpression = factory.createValueExpression( elContext, "" + subClient.getId(), Long.class );
                item.addActionListener( new SwitchableSetPropertyActionListener( targetExpression, valueExpression ) );
    
                this.subClientMenuModel.addMenuItem( item );
            }
        }
    }
    

    这将/应该适用于较新的 Mojarra 版本。 (废话)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-10
      相关资源
      最近更新 更多