You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:38:37