PrimeFaces动态菜单:不能删除相同的组件两次和ID生成



我在<p:dataTable>中有一个<p:menu>,当升级到Mojarra 2.1.22(在GlassFish 3.1.2.2上)时,我们得到了不规则的FacesException s:

        <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()等?

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

使用简单的请求作用域的菜单创建bean,这个问题甚至在PrimeFaces 3.5.28上也解决了:

@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版本一起工作。(咄)

相关内容

  • 没有找到相关文章

最新更新