在每个循环中的表单上使用嵌套资源和html类Rails Ajax

Rails Ajax on a form inside an each loop with nested resources and html class

本文关键字:资源 嵌套 html Ajax Rails 循环 表单      更新时间:2024-04-09

因此,我试图在目标中创建一个任务列表,为了完成这些任务,我创建了一个带有隐藏字段的form_for,该字段将在单击提交时更新每个任务记录的值。我正在尝试将ajax添加到表单中,这样当用户点击提交时,它将更新任务的记录,并呈现一个部分,用一个表示"完成!"的div替换此表单。

目标控制器.rb

def show
  @goal = Goal.where(user_id: current_user, id: params[:id]).first
  @goal_tasks = @goal.tasks
  # This is where the AJAX request will happen
  respond_to do |format|
    format.html {}
    format.js {}
  end
end

show.html.erb用于目标

    <% @goal_tasks.each do |task| %>
        <div class="complete-button">
            <% if task.completed == false %>
                <%= form_for([@goal,task], remote: true) do |f| %>
                    <%= f.hidden_field :completed , :value => true %>
                    <%= f.submit "Complete" , :class => "submit-complete" %>
                <% end %>
            <% else %>
                <%= render partial: "goals/taskcompleted"  %>
            <% end %>
        <div>
    <% end %>

show.js.erb

$(".complete-button").html("<%= j(render partial: 'goals/taskcompleted') %>")

正在发生的行为是,如果有多个任务,那么html中就会有多个具有唯一id="edit_task_unique_id"的表单,但由于我正在show.js.erb中获取.complete-button类。这是用完整的div替换所有表单。我曾试图以某种方式获取表单为每个任务创建的唯一id,但没有成功。感谢任何帮助或反馈!

Show是GET类型,您所做的是PUT类型。您可以使用更新方法或创建自定义方法。您甚至不需要表单,因为您不希望用户键入任何内容。在此之上,我将使用:completed_at字段和datetime类型。如果它为零,那么它就没有完成,如果它不是零(有一个日期时间),那么它就是完成了。

routes.rb

resources :goals do
  resources :tasks do
    member do
      patch :complete
    end
  end
end

goals/show.html.erb

 ....
 <%= render @tasks %> # this is a rails convention. Basically it iterates thru the @tasks and renders each task based on _task.html.erb which represents a single task.
 ....

tasks/_task.html.erb

#You use task instead of @task as you do within a @tasks.each |task| do block.
<%= task.name %>
<%= task.content %>
<% if task.completed_at.nil? %>
  #here you only need to pass task.id to the path (rails convention again)
  <%= link_to "Complete Task", complete_goal_task_path(id: task.id), action: :complete, remote: true, method: :patch %>
<% end %>

目标控制器

def show
  # I don't know why you wrote this:
  @goal = Goal.where(user_id: current_user, id: params[:id]).first
  #It should be just this since you are on the show page (You should define the current_user in the view link helper that takes the user on this page.)
  @goal = Goal.find(params[:id])
  @tasks = @goal.tasks
end

任务控制器

def complete
  @task = Task.find(params[:id])
  @task.update_attribute(:completed_at, Time.zone.now)
  respond_to do |format|
    format.html
    format.js
  end
end

tasks/complete.js.erb

//You remove the completed task from the DOM (I guess you wanna do that.)
$("#task_<%= @task.id %>").fadeOut(400, function(){
  $(this).remove();
});
//For flash checkout a stackoverflow question. Something like "how to use flash in js.erb"

schema.rb

create_table "tasks", force: :cascade do |t|
  t.integer  "goal_id",  null: false
  t.string   "name"
  t.text     "content",      null: false
  t.datetime "deadline",     null: false
  t.datetime "completed_at"
  t.datetime "created_at",   null: false
  t.datetime "updated_at",   null: false
end