Grails 5.3.2中g:sortableColumn点击后刷新整页而非容器问题
解决Grails 5.3.2中g:sortableColumn局部刷新容器的问题
核心思路
g:sortableColumn默认生成普通跳转链接,点击会触发整页刷新。要实现局部更新,需通过JS拦截点击事件,改用AJAX请求获取数据片段后替换目标容器内容,和uc:remotePaginate的逻辑对齐。
具体实现步骤
1. 保留现有g:sortableColumn标签
页面中正常使用g:sortableColumn,它会自动生成带sort和order参数的链接:
<table> <thead> <tr> <g:sortableColumn property="name" title="名称" class="sortable" /> <g:sortableColumn property="createDate" title="创建时间" class="sortable" /> <!-- 其他列 --> </tr> </thead> <tbody id="searchResultsContainer"> <!-- 渲染数据的模板内容 --> <g:render template="searchResults" model="[results: results]" /> </tbody> </table> <uc:remotePaginate total="${resultsCount}" />
2. 绑定AJAX点击事件
用jQuery拦截排序链接的点击,阻止默认跳转,发起AJAX请求更新容器:
// 页面加载完成后绑定事件 $(function() { bindSortableColumnEvents(); }); // 封装绑定逻辑,方便AJAX更新后重新绑定 function bindSortableColumnEvents() { $('th a.sortable').off('click').on('click', function(e) { e.preventDefault(); const targetUrl = $(this).attr('href'); // 用load方法加载目标页面的片段,更新容器 $('#searchResultsContainer').load(targetUrl + ' #searchResultsContainer', function() { // 重新绑定排序事件(因为容器内容更新了) bindSortableColumnEvents(); // 如果分页组件需要重新初始化,也在这里处理 }); }); }
3. 控制器确保返回片段而非整页
后端逻辑和分页复用,只需判断是否为AJAX请求,返回对应模板:
def list() { def sortField = params.sort ?: 'id' def sortOrder = params.order ?: 'asc' def max = params.max ? params.max.toInteger() : 10 def offset = params.offset ? params.offset.toInteger() : 0 def results = YourDomainClass.createCriteria().list(max: max, offset: offset) { order(sortField, sortOrder) // 其他查询条件 } if (request.xhr) { // AJAX请求只返回数据片段模板 render template: 'searchResults', model: [results: results] } else { // 非AJAX请求返回完整页面 respond results, model: [resultsCount: results.totalCount] } }
4. 注意事项
- 确保
searchResults模板仅包含表格tbody内的内容,不包含完整页面结构 - 如果使用了其他JS组件(如日期选择器),需在AJAX更新后重新初始化
- 检查
uc:remotePaginate的请求参数,确保排序参数(sort/order)和分页参数(max/offset)能被后端正确接收
内容的提问来源于stack exchange,提问作者Daniel Geiselman
相关产品推荐
相关产品推荐

