【问题标题】:How do I implement remote: true functionality without link_to?如何在没有 link_to 的情况下实现远程:真正的功能?
【发布时间】:2017-10-13 15:47:58
【问题描述】:

我正在尝试实现嵌套模型,这里是路由文件入口:

resources :projects do
  resources :instances
end

以下是项目控制器的sn-p:

# GET /projects/new
def new
  @project = Project.new
  @project.instances.build
end

和项目的表单视图:

<%= simple_form_for(@project) do |f| %>
  ...
  <%= label_tag :instance_count, "Instance Count" %>
  <%= select_tag :instance_count, options_for_select([0, 1, 2, 3, 4, 5], 0) %>
  ...
<% end %>

现在,当我更改实例计数时,我需要在上述表单下方多次显示实例字段。这是部分代码:

<%= form.simple_fields_for :instances do |i| %>
  ...  
<% end %>

基本上我需要从项目的 javascript 文件中调用 &lt;%= render 'instances/form', form: f %&gt;。它应该像链接remote: true 选项一样工作。但在这种情况下,没有链接,但在更改事件时需要显示表单。我应该如何实现这个?

【问题讨论】:

  • 当您点击@project[:instance_count] 并更改数字时,您想显示不同数量的instances 输入字段吗?这需要AJAX吗?也许在那个 div 上听那个点击事件就足够了,在那个页面上附加一个新的 div,当你提交表单时,确保提交适用于这些字段..我正在考虑发布一个答案..添加输入字段有点棘手,因为表单有一个避免 CSRF 的token,也可能需要使用Javascript 执行提交,并且您需要创建一个 jquery .post() 请求
  • 您的触发器听到的是点击&lt;%= select_tag :instance_count, options_for_select([0, 1, 2, 3, 4, 5], 0) %&gt; 所以$('#select_tab').click( // add input div to the page depending on the div .value() result );,没有服务器交互。然后你需要用这个函数api.jquery.com/jQuery.post在javascript文件中做post请求

标签: javascript ruby-on-rails simple-form


【解决方案1】:

我建议你使用https://github.com/nathanvda/cocoon

或者您可以使用类似的方法:以初始形式呈现部分(使用 display:none),然后使用 js 删除并保存部分字段,并在点击选择器时将它们克隆到表单。

【讨论】:

    【解决方案2】:

    您必须调用一次服务器端代码,因为instances/form 包含只能在服务器端呈现的代码。
    首先,您必须进行 ajax 调用(例如 instance_new_path),然后您必须在该视图上呈现表单(instance_new.js.erb)。

    示例.js.erb

    $("#new_form").html("<%= escape_javascript(render partial: 'instances/form' ) %>");
    

    【讨论】:

    • 传递表单对象是一个棘手的问题(我发现) - 你如何让部分可用?
    • 这必须在控制器上完成,也可以在提供完整代码后完成。
    【解决方案3】:

    标准是制作一个名为app/views/instances/_instance_fields.html.erb的部分。然后您可以将其加载到您的表单中并使其隐藏。

    <%= simple_form_for(@project) do |f| %>
      <%= render 'instances/_instance_fields %>
    <% end %>
    

    用某种容器覆盖_instance_fields 部分,例如&lt;fieldset class='instance_fields' style='display:none'&gt;。此外,您不应该在那里使用表单对象,只需在那里使用 text_field_tag/checkbox_tag 输入。然后,当您需要添加更多实例时,您只需根据需要多次复制此隐藏的 sn-ps 并设置输入的正确名称(适用于accepts_nested_attributes_for)。

    联系我以提供更多详细信息和帮助。这是在实际项目中使用的一种方法。每次需要添加更多实例时触发 ajax 调用根本没有优化。

    【讨论】:

    • 您需要将此片段存储在某个隐藏模板中,并为每个新实例复制此模板。复制后,您需要在 javascript 的帮助下设置正确的名称。正确的一些具体说明在我给你的方法中什么不起作用。您不应该使用 from 属性。在模板的情况下绝对没用,因为您仍然需要在 javascript 中手动处理输入 name 属性
    【解决方案4】:

    创建一个.js 文件,并将其加载到projects/new.html.erb 中,只要select 值发生变化,该文件就会执行,并向instances/new 控制器创建一个post 请求,该控制器将呈现instances/new.js.erb 每个它被击中的时间。

    # GET /instances/new
    def new
      @f = Instance.new
    end
    

    instances/new.js.erb

    $('#instance-form-wrapper').append(<% escape_javascript(render 'instances/form', form: @f) %>
    

    加载.js

    $(document).on('change', 'select#some-id-name', function(){
      var v = $(this).val();
      $('#instance-form-wrapper').html('') ;
      while(v--) $.post('/instances/');
    }) 
    

    虽然你应该这样使用。而是在您的代码中加载一个 instance 字段,将其隐藏,因为您的 project 中已经有 instance 可用。此外,每次渲染时都不需要任何新数据。只需选择值 1,您就可以 show 您的 instance 字段,如果值为 &gt; 1,您可以使用 clone 进一步复制它。

    【讨论】:

      【解决方案5】:

      只需将 gem https://github.com/nathanvda/cocoon 用于嵌套表单

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-24
        • 1970-01-01
        • 2011-09-16
        • 2010-09-10
        相关资源
        最近更新 更多