Rails新手求助:点击更新按钮切换文本框与标签并保留数据
嘿,作为Rails新手能想到做这个交互真的挺不错的!我来帮你实现这个点击更新按钮就切换成可编辑文本框、按钮变确认状态的功能,给你两种方案,推荐用无刷新的那种体验更好:
方案一:无刷新AJAX交互(推荐)
这种方式不用刷新页面,用户体验更流畅,咱们分三步来搞:
1. 修改ERB视图代码
把需要编辑的字段分成「显示状态」和「编辑状态」,默认显示状态,点击按钮后切换:
%tr[fund_flow] %td= fund_flow.symbol %td= fund_flow.trade_date %td <!-- 数值显示状态 --> <span class="nav-display" data-id="<%= fund_flow.id %>" data-value="<%= fund_flow.nav %>"> <%= number_to_currency(fund_flow.nav, unit: '') %> </span> <!-- 编辑输入框(默认隐藏) --> <%= text_field_tag "nav_#{fund_flow.id}", fund_flow.nav, class: 'nav-input', style: 'display: none;' %> %td <span class="shares-display" data-id="<%= fund_flow.id %>" data-value="<%= fund_flow.shares_outstanding %>"> <%= number_to_currency(fund_flow.shares_outstanding, unit: '') %> </span> <%= text_field_tag "shares_#{fund_flow.id}", fund_flow.shares_outstanding, class: 'shares-input', style: 'display: none;' %> %td <!-- 更新按钮 --> <button class="edit-btn" data-id="<%= fund_flow.id %>">更新</button> <!-- 确认按钮(默认隐藏) --> <button class="confirm-btn" data-id="<%= fund_flow.id %>" style="display: none;">确认</button>
2. 添加JavaScript交互逻辑
把这段代码放到app/javascript/packs/fund_flows.js里,或者直接写在视图的<script>标签中:
document.addEventListener('DOMContentLoaded', function() { // 监听「更新」按钮点击,切换到编辑状态 document.querySelectorAll('.edit-btn').forEach(btn => { btn.addEventListener('click', function() { const fundId = this.dataset.id; // 切换数值显示/输入框的可见性 document.querySelector(`.nav-display[data-id="${fundId}"]`).style.display = 'none'; document.querySelector(`.nav-input[name="nav_${fundId}"]`).style.display = 'inline-block'; document.querySelector(`.shares-display[data-id="${fundId}"]`).style.display = 'none'; document.querySelector(`.shares-input[name="shares_${fundId}"]`).style.display = 'inline-block'; // 切换按钮状态 this.style.display = 'none'; document.querySelector(`.confirm-btn[data-id="${fundId}"]`).style.display = 'inline-block'; }); }); // 监听「确认」按钮点击,提交更新请求 document.querySelectorAll('.confirm-btn').forEach(btn => { btn.addEventListener('click', function() { const fundId = this.dataset.id; const navValue = document.querySelector(`.nav-input[name="nav_${fundId}"]`).value; const sharesValue = document.querySelector(`.shares-input[name="shares_${fundId}"]`).value; // 用AJAX提交更新请求到后端 fetch(`/fund_flows/${fundId}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify({ fund_flow: { nav: navValue, shares_outstanding: sharesValue } }) }) .then(response => response.json()) .then(data => { // 更新页面显示的数值 const navDisplay = document.querySelector(`.nav-display[data-id="${fundId}"]`); navDisplay.textContent = data.nav_formatted; navDisplay.dataset.value = data.nav; const sharesDisplay = document.querySelector(`.shares-display[data-id="${fundId}"]`); sharesDisplay.textContent = data.shares_formatted; sharesDisplay.dataset.value = data.shares_outstanding; // 切换回显示状态和更新按钮 document.querySelector(`.nav-input[name="nav_${fundId}"]`).style.display = 'none'; navDisplay.style.display = 'inline-block'; document.querySelector(`.shares-input[name="shares_${fundId}"]`).style.display = 'none'; sharesDisplay.style.display = 'inline-block'; this.style.display = 'none'; document.querySelector(`.edit-btn[data-id="${fundId}"]`).style.display = 'inline-block'; }) .catch(error => console.error('更新失败:', error)); }); }); });
3. 调整后端控制器(FundFlowsController)
确保update动作能处理AJAX请求,返回格式化后的数值:
def update @fund_flow = FundFlow.find(params[:id]) if @fund_flow.update(fund_flow_params) # 返回格式化好的数值,方便前端直接显示 nav_formatted = number_to_currency(@fund_flow.nav, unit: '') shares_formatted = number_to_currency(@fund_flow.shares_outstanding, unit: '') render json: { nav: @fund_flow.nav, nav_formatted: nav_formatted, shares_outstanding: @fund_flow.shares_outstanding, shares_formatted: shares_formatted } else render json: { errors: @fund_flow.errors.full_messages }, status: :unprocessable_entity end end private def fund_flow_params params.require(:fund_flow).permit(:nav, :shares_outstanding) end
方案二:页面刷新式切换(适合简单场景)
如果暂时不想搞AJAX,也可以用页面刷新的方式实现:
%tr[fund_flow] %td= fund_flow.symbol %td= fund_flow.trade_date %td <% if params[:edit_id] == fund_flow.id.to_s %> <%= text_field_tag "fund_flow[nav]", fund_flow.nav %> <% else %> <%= number_to_currency(fund_flow.nav, unit: '') %> <% end %> %td <% if params[:edit_id] == fund_flow.id.to_s %> <%= text_field_tag "fund_flow[shares_outstanding]", fund_flow.shares_outstanding %> <% else %> <%= number_to_currency(fund_flow.shares_outstanding, unit: '') %> <% end %> %td <% if params[:edit_id] == fund_flow.id.to_s %> <%= form_with(model: fund_flow, method: :patch) do |f| %> <%= f.hidden_field :nav %> <%= f.hidden_field :shares_outstanding %> <%= f.submit '确认更新' %> <% end %> <% else %> <%= link_to '更新', fund_flows_path(edit_id: fund_flow.id), method: :get %> <% end %>
这种方式点击「更新」会刷新页面进入编辑状态,提交后再刷新回到显示状态,逻辑更简单,但体验不如无刷新的方案。
内容的提问来源于stack exchange,提问作者M.Nar
相关产品推荐
相关产品推荐

