如何在不关闭下拉列表的情况下更新PrimeFaces SelectOneMenu
问题原因
当通过focus事件触发Ajax更新整个SelectOneMenu组件时,组件会被重新渲染,导致已展开的下拉列表丢失状态而关闭。
解决方案1:仅更新选项列表(推荐)
不要更新整个SelectOneMenu,而是将<f:selectItems>包裹在一个<p:outputPanel>中,仅更新这个面板。这样组件的整体DOM结构不会被替换,下拉展开状态得以保留。
修改后的代码:
<p:selectOneMenu id="companyEntity" value="#{docBean.docIncomingEntity.companyEntity}" effect="fade" rendered="#{docBean.companyPersonSwitch == 0}" filter="true" converter="omnifaces.SelectItemsConverter" filterMatchMode="contains"> <p:outputPanel id="companyOptions"> <f:selectItems value="#{companyBean.companyEntityList}" itemLabel="#{item.name}" itemValue="#{item}" var="item"/> </p:outputPanel> <p:ajax event="focus" listener="#{companyBean.loadAllCompaniesList()}" update="companyOptions"/> </p:selectOneMenu>
解决方案2:Ajax完成后重新打开下拉
如果必须更新整个组件,可以利用PrimeFaces的客户端API,在Ajax请求完成后重新展开下拉菜单。需要给组件添加widgetVar属性:
修改后的代码:
<p:selectOneMenu id="companyEntity" widgetVar="companyEntityWidget" value="#{docBean.docIncomingEntity.companyEntity}" effect="fade" rendered="#{docBean.companyPersonSwitch == 0}" filter="true" converter="omnifaces.SelectItemsConverter" filterMatchMode="contains"> <f:selectItems value="#{companyBean.companyEntityList}" itemLabel="#{item.name}" itemValue="#{item}" var="item"/> <p:ajax event="focus" listener="#{companyBean.loadAllCompaniesList()}" update="companyEntity" oncomplete="PF('companyEntityWidget').show()"/> </p:selectOneMenu>
额外优化:避免重复加载数据
为了防止每次触发focus都重复请求数据,可以在后端Bean中添加一个加载标记,仅在首次触发时加载数据:
private boolean companiesLoaded = false; private List<CompanyEntity> companyEntityList; public void loadAllCompaniesList() { if (!companiesLoaded) { // 替换为你的数据加载逻辑 companyEntityList = yourCompanyService.getAllCompanies(); companiesLoaded = true; } }
内容的提问来源于stack exchange,提问作者Pegus
相关产品推荐
相关产品推荐

