PrimeFaces p:dataTable右键contextMenu事件触发浏览器默认菜单问题
PrimeFaces dataTable 右键菜单自动选行+屏蔽默认菜单方案
问题场景
基于PrimeFaces 11.0.0的<p:dataTable>实现人员列表展示与删除功能时,存在以下逻辑冲突:
- 初始配置下,必须先左键选中行完成
selection值更新,才能右键打开上下文菜单执行删除,直接右键点击行时选中值为空,删除操作失效 - 手动添加
<p:ajax event="contextMenu"/>尝试实现右键自动选行后,浏览器默认右键菜单会始终显示在自定义上下文菜单上层,造成遮挡 - 要求不编写自定义JavaScript,同时实现两个目标:
- 右键点击行时自动更新绑定的选中值
- 表格区域右键不弹出浏览器默认菜单
初始问题代码如下:
<p:dataTable id="personTable" var="person" value="#{model.getPersons()}" selectionMode="single" selection="#{model.personSelection}" scrollable="true" rowKey="#{person.id}" scrollHeight="200" disableContextMenuIfEmpty="true"> <p:ajax event="rowSelect" /> <p:ajax event="rowDblselect" update="@widgetVar(personDialog)" oncomplete="PF('personDialog').show()" /> <p:column headerText="Name" sortable="true" sortBy="#{person.firstName}"> <h:outputText value="#{person.firstName}" /> </p:column> <p:column headerText="Address" sortable="true" sortBy="#{person.address}"> <h:outputText value="#{person.address}" /> </p:column> </p:dataTable> <p:contextMenu for="personTable" id="ctxPerson"> <p:menuitem value="Delete" update="personTable" partialSubmit="true" process="@this" ajax="true" actionListener="#{personService.removePerson(model)}" /> </p:contextMenu>
解决方法
不需要额外添加ajax标签,也不需要写自定义JavaScript,直接使用<p:contextMenu>原生支持的rowSelect属性即可,修改步骤:
- 移除手动添加的
<p:ajax event="contextMenu"/>标签(该标签不会自动阻止浏览器默认右键事件,是导致默认菜单弹出遮挡的核心原因) - 为
<p:contextMenu>标签添加rowSelect="true"属性,该属性会让上下文菜单组件在触发前自动选中当前右键点击的行,同时组件内部会自动拦截浏览器默认右键事件,阻止默认菜单弹出。
修改后的上下文菜单代码如下:
<p:contextMenu for="personTable" id="ctxPerson" rowSelect="true"> <p:menuitem value="Delete" update="personTable" partialSubmit="true" process="@this" ajax="true" actionListener="#{personService.removePerson(model)}" /> </p:contextMenu>
效果验证
修改后可完全满足需求:
- 直接右键点击任意未选中的行,
#{model.personSelection}会自动同步为当前行对应的人员对象,删除操作可正常获取选中值执行 - 自定义上下文菜单弹出时不会触发浏览器默认右键菜单,不存在遮挡问题
- 所有逻辑基于PrimeFaces 11.0.0原生属性实现,无额外自定义JS代码,无版本兼容问题
内容的提问来源于stack exchange,提问作者XtremeBaumer
相关产品推荐
相关产品推荐

