Primefaces:不同标签页中两个组件的Ajax更新失效问题
问题分析与解决方案
核心问题出在**动态标签页(dynamic="true")+缓存(cache="true")**的机制上:未激活的标签页内容不会被渲染到页面DOM中,Ajax更新时找不到目标复选框元素,自然无法同步状态。另外你的代码里还有几处细节错误需要修正:
1. 先修正基础错误
- 前台xhtml中绑定的变量
#{backingBean.toogleBool}和后台bean的toggleMailAnhangExtrahieren名称不匹配,先把前台的绑定改为#{backingBean.toggleMailAnhangExtrahieren} - Ajax更新选择器用的是
@(.toggle2),但toggle2是复选框的id而非class,应该用class选择器(避免命名容器拼接id的问题)
2. 解决动态标签页的DOM渲染问题
因为未激活的标签页内容不在DOM里,必须先让目标标签页的内容被加载,才能更新其中的复选框。可以通过PrimeFaces的tabView widget来触发目标标签页的加载,再执行更新。
修改后的xhtml代码示例
<p:tabView id="tabsView" widgetVar="tabPanelWidget" dynamic="true" cache="true"> <p:tab id="tab1"> <p:outputPanel id="panel1"> <p:fieldset toggleable="false"> <p:panelGrid id="panelGrid1"> <p:row> <p:column> <p:outputLabel for="toggle1" value="Toggle 1"/> <p:selectBooleanCheckbox id="toggle1" value="#{backingBean.toggleMailAnhangExtrahieren}" class="sync-checkbox"> <p:ajax update="@(.sync-checkbox)" oncomplete="PF('tabPanelWidget').loadTab(1);"/> </p:selectBooleanCheckbox> </p:column> </p:row> </p:panelGrid> </p:fieldset> </p:outputPanel> </p:tab> <p:tab id="tab2"> <p:outputPanel id="panel2"> <p:fieldset toggleable="false"> <p:panelGrid id="panelGrid2"> <p:row> <p:column> <p:outputLabel for="toggle2" value="Toggle 2"/> <p:selectBooleanCheckbox id="toggle2" value="#{backingBean.toggleMailAnhangExtrahieren}" class="sync-checkbox"> <p:ajax update="@(.sync-checkbox)" oncomplete="PF('tabPanelWidget').loadTab(0);"/> </p:selectBooleanCheckbox> </p:column> </p:row> </p:panelGrid> </p:fieldset> </p:outputPanel> </p:tab> </p:tabView>
关键说明
class="sync-checkbox":给两个复选框添加统一的class,确保Ajax能选中所有需要同步的元素oncomplete="PF('tabPanelWidget').loadTab(1);":在Ajax请求完成后,调用tabView的widget方法加载目标标签页(索引从0开始),这样目标标签页的内容会被渲染到DOM中,后续的update="@(.sync-checkbox)"就能找到并更新它- 如果不想切换到目标标签页,只是偷偷加载内容,
loadTab()方法不会切换标签,只会渲染内容到DOM;如果需要切换标签,把loadTab()换成select()即可
3. 替代方案(简单但性能略差)
如果不需要动态加载标签页的性能优化,可以直接把dynamic="true"和cache="true"去掉,这样所有标签页内容会初始渲染到DOM中,此时只需要用class选择器更新即可,不需要额外的widget调用。
内容的提问来源于stack exchange,提问作者Christian O.
相关产品推荐
相关产品推荐

