嵌套表单的多个字段类型

时间:2018-11-04 15:57:57

标签: javascript ajax forms ruby-on-rails-4 nested-forms

我的应用有位置,每个位置都有很多IP。使用railscasts相关情节(http://railscasts.com/episodes/197-nested-model-form-part-2),我构建了一个location表单,其中包含ip列表和添加新选项的选项。每个ip的{​​{1}}由表单生成。

事实是,我希望现有的text_field显示为ip而不是可编辑的文本框,如下所示:

  • 已存在(只读)

  • 已存在(只读)

  • 已存在(只读)

新链接

,然后单击链接,将附加一个可编辑的文本框。有什么想法吗?


模型

location.rb

label

ip.rb

class Ip < ActiveRecord::Base
  belongs to :location
  validates_uniqueness_of :address
  [...]
end

控制器

class Location < ActiveRecord::Base
  has_many :ips
  accepts_nested_attributes_for :ips
  [...]
end

助手

class LocationsController < ApplicationController
  [...]
  def location_params
    params.require(:location).permit(:name, ips_attributes: [:id, :address])
  end
end

观看次数

/locations/_form.html.erb

module ApplicationHelper
  [...]  
  def link_to_add_fields(name, f, association)
    new_obj = f.object.class.reflect_on_association(association).klass.new
    fields = f.fields_for(association, new_obj, :child_index => "new_#{association}") do |builder|
      render(association.to_s.singularize + "_fields", :f => builder)
    end
    link_to name, "#", onclick: "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"
  end
end

_ip_fields.html.erb

<header>
  <script>
    function add_fields(link, association, content) {
      var new_id = new Date().getTime();
      var regexp = new RegExp("new_" + association, "g")
      $(link).parent().before(content.replace(regexp, new_id));
    }
  </script>
</header>
<%= form_for @location do |f| %>
  [...]
  <%= f.label :ips, t('location.ips') %>
  <%= f.fields_for :ips do |builder| %>
    <%= redner "ip_fields", f: builder %>
  <% end %>
  <p>
    <%= link_to_add_fields t('location.add_ip'), f, :ips %>
  </p>
  [...]
<% end %>

相关的HTML:

<p class="fields">
  <%= f.text_field :address %>
</p>

1 个答案:

答案 0 :(得分:0)

嗯,这不是很漂亮(不建议在视图中使用逻辑),但是它提供了我想要的解决方案:helper方法中的一个额外参数用于发信号通知未标记的字段,然后重构部分条件条件这个变量的存在

助手:

module ApplicationHelper
  [...]  
  def link_to_add_fields(name, f, association)
    new_obj = f.object.class.reflect_on_association(association).klass.new
    fields = f.fields_for(association, new_obj, :child_index => "new_#{association}") do |builder|
      render(association.to_s.singularize + "_fields", :f => builder, labelled: false)
    end
    link_to name, "#", onclick: "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"
  end
end

_ip_fields.html.erb

<p class="fields">
  <% if (defined? labelled) %>
    <%= f.text_field :address %>
  <% else %>
    <%= f.label :address, f.object.address %>
  <% end %>
</p>