Primefaces graphicImage Ajax删除后不刷新问题求助
这个问题我之前也碰到过,核心原因是你用了JSTL的<c:forEach>来渲染图片列表,而不是JSF原生的<ui:repeat>组件,导致Ajax更新时页面无法重新生成最新的图片组件。下面给你详细的解决方案:
问题根源
<c:forEach>是JSTL标签,它在视图构建阶段(页面首次加载时)就执行完毕,生成对应的JSF组件树。当你通过Ajax删除图片后,虽然后台Bean里的hm2已经更新,但JSF在重新渲染时只会复用之前构建好的组件树,不会重新执行<c:forEach>,所以页面上还是显示原来的图片列表。
而<ui:repeat>是JSF的迭代组件,它在视图渲染阶段执行,每次渲染(包括Ajax更新后的渲染)都会遍历当前的hm2集合,生成最新的组件,完美适配Ajax场景。
解决方案步骤
- 替换
<c:forEach>为<ui:repeat>
修改你的JSF页面代码,把遍历图片列表的<c:forEach>换成<ui:repeat>,注意要遍历hm2的entrySet()(因为hm2是LinkedHashMap,<ui:repeat>需要明确遍历集合):
<h:form id="tempForm" enctype="multipart/form-data"> <h:panelGroup id="graphicImageCustomerPicturePanel"> <div class="card"> <p:panelGrid columns="2" columnClasses="ui-grid-col-6,ui-grid-col-6" layout="grid" styleClass="ui-panelgrid-blank form-group" style="border:0px none; background-color:transparent;"> <!-- 用ui:repeat替换c:forEach,遍历hm2的entry集合 --> <ui:repeat var="entry" value="#{tempBean.hm2.entrySet()}"> <h:panelGroup> <p:commandLink> <p:graphicImage style="height: 280px; width: 280px; margin-right: 10px;" title="#{entry.value.name}" value="#{entry.value}" stream="false" cache="false"/> <p:ajax event="click" listener="#{tempBean.handlePictureSelect(entry.value.name)}" process="@this" update="dlg"/> </p:commandLink> <p:commandButton value="Remove" ajax="true" actionListener="#{tempBean.removePicture(entry.key)}" update="graphicImageCustomerPicturePanel" style="width: 280px"/> </h:panelGroup> </ui:repeat> </p:panelGrid> <!-- 以下fileUpload和按钮代码保持不变 --> <p:fileUpload auto="true" mode="advanced" update="graphicImageCustomerPicturePanel" fileUploadListener="#{tempBean.handleFileUploadCustomerPicture}" required="false" requiredMessage="File Should not be empty!" id="pictureUploadCustomerPicture" value="#{tempBean.uploadedFileCustomerPicture}"> </p:fileUpload> <p:commandButton value="Save Pictures" action="#{tempBean.savePictures('save')}" ajax="false"> <f:param name="reportTitle" value="Manage Customers"/> </p:commandButton> <p:commandButton value="Update Pictures" action="#{tempBean.savePictures('update')}" ajax="false"> <f:param name="reportTitle" value="Manage Customers"/> </p:commandButton> </div> </h:panelGroup> </h:form>
确保Bean是
@ViewScoped
你的托管Bean必须使用@ViewScoped注解(而不是@RequestScoped),这样Bean的状态会在整个视图生命周期中保持,Ajax请求不会重置hm1和hm2集合。如果之前是@RequestScoped,删除操作看似后台执行,但实际上是在新的Bean实例上操作,当前视图的Bean状态并没有改变。验证辅助方法完整性
确保你的cloneInputStreamAndDefaultStreamedContent方法是完整的(你提供的代码片段末尾不完整),这个方法负责克隆输入流和生成DefaultStreamedContent,只有它正常工作,剩余的图片才能正确渲染。
额外说明
你已经设置了p:graphicImage的cache="false",这一点做得很好,它能避免浏览器缓存已删除的图片,确保页面显示最新的内容。
内容的提问来源于stack exchange,提问作者Usman Aslam

