在 Rails 中动态添加表单字段是一个常见的需求,特别是在处理具有多个关联对象的表单时。例如,如果你有一个 Project
模型,它可以有多个 Tasks
,你可能希望在创建或编辑项目时能够动态地添加多个任务。
这里将介绍如何使用 Rails、JavaScript(或 jQuery)来实现动态添加表单字段的功能。
首先,确保你的模型之间的关系已经正确设置。以 Project
和 Task
为例:
# app/models/project.rb
class Project < ApplicationRecord
has_many :tasks, dependent: :destroy
accepts_nested_attributes_for :tasks, allow_destroy: true, reject_if: proc { |attributes| attributes['name'].blank? }
end
# app/models/task.rb
class Task < ApplicationRecord
belongs_to :project
end
在你的控制器中,确保在 new
和 edit
动作中初始化任务对象,并在 project_params
中允许任务的参数。
# app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
def new
@project = Project.new
@project.tasks.build
end
def edit
@project = Project.find(params[:id])
end
private
def project_params
params.require(:project).permit(:name, tasks_attributes: [:id, :name, :_destroy])
end
end
在你的表单视图中,使用 fields_for
来处理嵌套的任务对象。
<!-- app/views/projects/_form.html.erb -->
<%= form_with(model: project, local: true) do |form| %>
<%= form.label :name %>
<%= form.text_field :name %>
<%= form.fields_for :tasks do |task_form| %>
<%= render 'task_fields', f: task_form %>
<% end %>
<div class='links'>
<%= link_to_add_fields "Add Task", form, :tasks %>
</div>
<%= form.submit %>
<% end %>
你需要编写一个 JavaScript 功能来动态添加任务字段。这里使用 jQuery 来简化 DOM 操作。
// app/javascript/packs/application.js 或者其他 JavaScript 文件
function link_to_add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g");
$(link).before(content.replace(regexp, new_id));
}
$(document).on('click', '.add_fields', function(e) {
e.preventDefault();
var link = $(this);
var association = $(this).data('association');
var content = $(this).data('content');
link_to_add_fields(link, association, content);
});
在你的 ApplicationHelper
中添加一个辅助方法来生成添加字段的链接。
# app/helpers/application_helper.rb
module ApplicationHelper
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
end
确保你的 JavaScript 和 Rails 视图正确地协同工作,以便在用户点击添加链接时,可以在表单中插入新的任务字段。这种方法允许你动态地添加任意数量的任务字段到你的项目表单中。
领取专属 10元无门槛券
手把手带您无忧上云