JSF中Ajax处理返回未更新HTML,commandLink无法更新ui:repeat子元素
看来你在JSF里用PrimeFaces的<p:commandLink>做Ajax更新时,碰到了ui:repeat子元素死活不刷新的问题——这种情况我之前也遇到过,大概率是数据源、组件ID定位或者作用域的问题,给你几个排查和解决的方向:
先确认
ui:repeat绑定的数据源真的更新了ui:repeat是基于内存中的集合渲染的,所以你的refresh方法里必须确保用来渲染子元素的集合已经被重新加载或者更新了。比如如果ui:repeat绑定的是bibliotecaDettaglioView.someList,那在refresh里要直接重新获取这个集合(比如someList = bookService.getUpdatedList();),而不是只修改集合里某个对象的属性——除非这个对象是可变的,且EL表达式能正确识别属性变化。如果集合的引用没变,JSF可能会认为数据没更新,跳过渲染。检查组件ID的定位是否正确
你在update属性里写的olProprietario、myXXX:itaRecensione这些ID,要确保它们的路径是对的:- 如果组件在根命名容器外(或者要全局查找),可以在ID前加冒号
:,比如:olProprietario,这样JSF会从最顶层开始找这个组件,避免和其他命名容器里的重名组件混淆; - 确认
myXXX是父命名容器的正确ID,有没有拼写错误; - 可以用浏览器开发者工具查看页面渲染后的真实客户端ID(比如F12看元素的id属性),然后把这个完整ID写到
update里试试。
- 如果组件在根命名容器外(或者要全局查找),可以在ID前加冒号
调整
process属性的范围
你现在设置的process="myX",如果myX没有包含触发更新所需的必要数据,可能导致后端的refresh方法没有正确执行。可以先把process改成@this(只处理当前commandLink),或者@form(处理整个表单),排除是否是process范围限制了数据提交或者方法执行。确保Bean的作用域正确
如果你的bibliotecaDettaglioView是请求作用域(@RequestScoped),那每次Ajax请求后Bean都会重新创建,之前的数据会丢失,自然刷新不了。建议改成视图作用域(@ViewScoped)——这是JSF处理页面内Ajax更新的最佳选择,既能保持页面状态,又不会像会话作用域那样占用过多资源。检查Ajax请求的响应内容
打开浏览器开发者工具(F12),切换到“网络”标签,找到这个Ajax请求,看看返回的响应HTML是不是已经是更新后的内容:- 如果响应里是新内容但页面没刷新,那可能是客户端DOM替换出了问题,试试清空浏览器缓存或者换个浏览器试试;
- 如果响应里还是旧内容,那问题肯定在后端——要么
refresh方法没执行,要么数据源没更新。
给你一个调整后的<p:commandLink>示例(加了全局ID的冒号,调整了process):
<p:commandLink value="#{bibliotecaDettaglioView.libro.titolo}" action="#{bibliotecaDettaglioView.refresh}" process="@this" update=":olProprietario :olTitle :csValutazione :giCopertina :olTrama :olGenere :olAutore :olAnno :olIsbn :myXXX:itaRecensione :myXXX:csVoto :myX"> </p:commandLink>
内容的提问来源于stack exchange,提问作者Fabio Piunti

