Rails评价表单结合jQuery星级选择器实现评分值提交的方案
Rails表单整合jQuery星级选择器的实现方案
核心原理
- 替换原有的
number_field为Rails表单生成的隐藏域,后端接收参数的逻辑完全不变,无需改动控制器、模型层代码 - 保留原有jQuery星级选择器的全部视觉交互逻辑,仅在用户点击星级时,将对应
data-value值实时写入隐藏域的value属性 - 表单正常提交时,隐藏域携带的星级值会和表单其他参数一同传到后端,和原有数字输入框的提交效果完全等价
第一步:改造表单代码
把原来星级选择部分的数字输入框替换为隐藏域,将现有jQuery星级组件嵌入表单分组内,完整代码结构如下:
<h1>以 <%= current_user.first_name %> <%= current_user.last_name %> 的身份发表评价</h1> <div class="border border-grey-light rounded" style ="padding: 10px;"> <%= image_tag current_user.avatar_thumbnail, class: "avatar", alt: "avatar" %> <%= form_with model: @testomonial do |f| %> <div class="mb-3"> <%= f.label :review, class: "label" %> <%= f.text_field :body, class: "form-control", placeholder: "在此填写评价内容" %> </div> <div class="mb-3"> <%= f.label :stars, class: "label" %> <%# 替换原有数字输入框为隐藏域,承接星级值 %> <%= f.hidden_field :star %> <%# 嵌入原有jQuery星级选择器结构 %> <div class='rating-stars text-center'> <ul id='stars'> <li class='star' title='较差' data-value='1'> <i class='fa fa-star fa-fw'></i> </li> <li class='star' title='一般' data-value='2'> <i class='fa fa-star fa-fw'></i> </li> <li class='star' title='较好' data-value='3'> <i class='fa fa-star fa-fw'></i> </li> <li class='star' title='非常好' data-value='4'> <i class='fa fa-star fa-fw'></i> </li> <li class='star' title='超赞' data-value='5'> <i class='fa fa-star fa-fw'></i> </li> </ul> </div> </div> <div class="mb-3"> <%= f.submit class: "btn btn-primary text-base py-1.5 px-5", value: "发布评价" %> </div> <% end %> </div>
第二步:修改jQuery逻辑,同步选中值
Rails生成的hidden_field默认id格式为[模型名]_[字段名],对应本项目就是#testomonial_star。在原有星级点击事件的逻辑末尾,增加将选中值写入隐藏域的代码即可,原有悬停高亮、选中态切换、提示消息的逻辑全部保留,无需改动。
改造后的完整jQuery代码:
$(document).ready(function(){ // 原有鼠标悬停高亮逻辑,保持不变 $('#stars li').on('mouseover', function(){ var onStar = parseInt($(this).data('value'), 10); $(this).parent().children('li.star').each(function(e){ if (e < onStar) { $(this).addClass('hover'); } else { $(this).removeClass('hover'); } }); }).on('mouseout', function(){ $(this).parent().children('li.star').each(function(e){ $(this).removeClass('hover'); }); }); // 原有点击选中逻辑,新增值同步代码 $('#stars li').on('click', function(){ var onStar = parseInt($(this).data('value'), 10); var stars = $(this).parent().children('li.star'); // 清除所有星级的选中态 for (i = 0; i < stars.length; i++) { $(stars[i]).removeClass('selected'); } // 点亮对应选中值的星级 for (i = 0; i < onStar; i++) { $(stars[i]).addClass('selected'); } // 核心功能:将选中的星级值同步到表单隐藏域 var ratingValue = parseInt($('#stars li.selected').last().data('value'), 10); $("#testomonial_star").val(ratingValue); // 原有提示消息逻辑 var msg = ""; if (ratingValue > 1) { msg = "感谢评价!您给了本内容 " + ratingValue + " 星。"; } else { msg = "我们会持续改进体验。您给了本内容 " + ratingValue + " 星。"; } responseMessage(msg); }); }); // 原有提示消息渲染函数 function responseMessage(msg) { $('.success-box').fadeIn(200); $('.success-box div.text-message').html("<span>" + msg + "</span>"); }
注意事项
- 若后续修改模型名或字段名,需要同步调整jQuery中选择隐藏域的id值,也可以在生成隐藏域时手动指定id值,避免拼写偏差:
<%= f.hidden_field :star, id: "rating-input" %>,对应jQuery选择器改为$("#rating-input")即可 - 隐藏域提交的参数格式与原有数字输入框完全一致,控制器中的强参数白名单、模型层的1-5分数值校验规则完全不需要改动
- 可在表单提交前增加简单校验:如果隐藏域的值为空,弹出提示引导用户选择星级,避免提交无效的空评分
内容的提问来源于stack exchange,提问作者Lorenzo_xavier
相关产品推荐
相关产品推荐

