【问题标题】:Rails 4 Ajax rendering partial multiple times on same page each time submit is hit每次点击提交时,Rails 4 Ajax 在同一页面上多次渲染部分
【发布时间】:2014-12-03 18:59:16
【问题描述】:

每次我在 Rails 应用程序中点击提交时,它都会发送 2 次请求。我可以通过点击刷新来摆脱第二部分。这是一个嵌套应用程序。 Todo has_many 项。我包括了控制器、创建和部分。 我附上了一张照片,以便更清楚地说明。

create.js.erb

$('.todo-items').prepend("<%= escape_javascript(render(@item)) %>");

Items Controller:

class ItemsController < ApplicationController
  before_action :set_item, only: [:show, :edit, :update, :destroy]
  before_action :set_todo
  respond_to :html, :js

  # GET /items
  # GET /items.json
  def index
    @items = Item.all
  end

  # GET /items/1
  # GET /items/1.json
  def show
    @item = Item.find(params[:id])
  end

  # GET /items/new
  def new
    @item = @todo.items.build
  end

  # GET /items/1/edit
  def edit
    @item = Items.find(params[:id])
  end

  # POST /items
  # POST /items.json
  def create
    @item = @todo.items.build(item_params)

    respond_with(@item) do |format|
      if @item.save
        format.html { redirect_to [@todo], notice: 'Item was successfully created.' }
        format.json { render :show, status: :created, location: @item }
      else
        format.html { render :new }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /items/1
  # PATCH/PUT /items/1.json
  def update
    @item = Item.find(params[:id])
    respond_to do |format|
      if @item.update(item_params)
        format.html { redirect_to [@todo, @item], notice: 'Item was successfully updated.' }
        format.json { render :show, status: :ok, location: @item }
      else
        format.html { render :edit }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /items/1
  # DELETE /items/1.json
  def destroy
    @item = Item.find(params[:id])
    @item.destroy

    respond_to do |format|
      format.html { redirect_to items_path }
      format.json { head :no_content }
      format.js   { render layout: false }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_item
      @item = Item.find(params[:id])
    end

    def set_todo
      @todo = Todo.find(params[:todo_id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def item_params
      params.require(:item).permit(:content, :todo_id)
    end
end

Todos Controller

class TodosController < ApplicationController
  respond_to :html, :js
  before_action :set_todo, only: [:show, :edit, :update, :destroy]

  # GET /todos
  # GET /todos.json
  def index
    @todos = Todo.all
    @todo = Todo.new
  end

  # GET /todos/1
  # GET /todos/1.json
  def show
    @todo= Todo.find(params[:id])
  end

  # GET /todos/new
  def new
    @todo = Todo.new
    #3.times{@todo.items.build}
  end

  # GET /todos/1/edit
  def edit
  end

  # POST /todos
  # POST /todos.json
  def create
    @todo = Todo.new(todo_params)
    #@todo.items.build

    respond_to do |format|
      if @todo.save
        format.html { redirect_to todo_path, notice: 'Todo was successfully created.' }
        format.json { render :show, status: :created, location: @todo }
      else
        format.html { render :new }
        format.json { render json: @todo.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /todos/1
  # PATCH/PUT /todos/1.json
  def update
    @todo = Todo.find(params[:id])
    respond_to do |format|
      if @todo.update(todo_params)
        format.html { redirect_to todos_url, notice: 'Todo was successfully updated.' }
        format.json { render :show, status: :ok, location: @todo }
      else
        format.html { render :edit }
        format.json { render json: @todo.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /todos/1
  # DELETE /todos/1.json
  def destroy
    @todo.destroy
    @todo.items.destroy
    respond_to do |format|
      format.html { redirect_to todos_url, notice: 'Todo was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def todo_completed
    @todo = Todo.find(params[:id])
    @todo.completed = true

    if @todo.save
      flash[:notice] = "Task was completed."
    else
      flash[:error] = "There was an error completing the task."
    end
    #redirect_to tasks_path

    respond_with(@todo) do |f|
      f.html { redirect_to todos_path }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_todo
      @todo = Todo.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def todo_params
      params.require(:todo).permit(:title, :completed, items_attributes: [:content,:completed, :_destroy])
    end
end

这是 Todo 照片中的展示页面。它正在渲染该特定待办事项下方的项目。

<p>Here are all the things you need to complete</p>

<div class="todo-items">
    <%= render partial: 'items/item' %>
</div>

<br>
<div class='new-item'>
  <%= render 'items/form'%>
</div>

<%= link_to 'Back', todos_path %>

项目/项目

<p>todo/show this is the partial <%= @todo.title %></p>
<table class='table table-bordered'>
  <thead>
    <tr>
      <th>Description</th>
      <th> Time Left </th>
      <th> Mark Complete </th>
    </tr>
  </thead>

  <tbody>
    <% @todo.items.each do |item| %>
      <tr>
        <td><%= link_to item.content, [@todo, item] %></td>
        <td><%= item.days_left %>
        <td>
            <%= link_to todo_item_path(@todo,item), method: :delete, data: { confirm: 'Are you sure?' }, remote: true, class: 'delete_item' do %>
                <i class="fa fa-check"></i>
            <% end %>
        </td>    
      </tr>
    <% end %>
  </tbody>
</table>

<br>
<p>end of partial item</p>

项目/形式

<p>
  <strong>Todo:</strong>
  <%= @todo.title %>
</p>

<%= form_for [@todo, @todo.items.build], remote: true do |f| %>
  <div class="field">
    <%= f.label :content %><br>
    <%= f.text_field :content %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

来自控制台的更多信息。它从我点击列表(杂货)开始,到我点击提交添加项目结束

Started GET "/todos/25" for 127.0.0.1 at 2014-10-08 19:19:58 -0500
Processing by TodosController#show as HTML
  Parameters: {"id"=>"25"}
  Todo Load (0.3ms)  SELECT  "todos".* FROM "todos"  WHERE "todos"."id" = ? LIMIT 1  [["id", 25]]
  CACHE (0.0ms)  SELECT  "todos".* FROM "todos"  WHERE "todos"."id" = ? LIMIT 1  [["id", "25"]]
  Item Load (0.4ms)  SELECT "items".* FROM "items"  WHERE "items"."todo_id" = ?  [["todo_id", 25]]
  Rendered items/_item.html.erb (42.9ms)
  Rendered items/_form.html.erb (17.3ms)
  Rendered todos/show.html.erb within layouts/application (66.6ms)
Completed 200 OK in 346ms (Views: 339.5ms | ActiveRecord: 1.3ms)


Started POST "/todos/25/items" for 127.0.0.1 at 2014-10-08 19:20:12 -0500
Processing by ItemsController#create as JS
  Parameters: {"utf8"=>"✓", "item"=>{"content"=>"Cereal"}, "commit"=>"Create Item", "todo_id"=>"25"}
  Todo Load (0.2ms)  SELECT  "todos".* FROM "todos"  WHERE "todos"."id" = ? LIMIT 1  [["id", 25]]
   (0.3ms)  begin transaction
  Todo Load (0.2ms)  SELECT  "todos".* FROM "todos"  WHERE "todos"."id" = ? LIMIT 1  [["id", 25]]
  SQL (0.5ms)  INSERT INTO "items" ("content", "created_at", "todo_id", "updated_at") VALUES (?, ?, ?, ?)  [["content", "Cereal"], ["created_at", "2014-10-09 00:20:12.060569"], ["todo_id", 25], ["updated_at", "2014-10-09 00:20:12.060569"]]
   (148.1ms)  commit transaction
  Item Load (0.2ms)  SELECT "items".* FROM "items"  WHERE "items"."todo_id" = ?  [["todo_id", 25]]
  Rendered items/_item.html.erb (9.8ms)
  Rendered items/create.js.erb (12.5ms)
Completed 200 OK in 180ms (Views: 15.2ms | ActiveRecord: 149.4ms)

【问题讨论】:

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


    【解决方案1】:

    问题在于您的 create.js.erb 文件。您有以下代码:

    $('.todo-items').prepend("<%= escape_javascript(render(@item)) %>");
    

    在此代码中,您在 todo-items 中预先设置了 html,您应该每次都替换项目。如下:

    $('.todo-items').html("<%= escape_javascript(render(@item)) %>");
    

    这将每次用新的 html 替换 html。

    【讨论】:

    • 谢谢!!!这是我第一次使用 Ajax。关于我可以在哪里了解更多信息的任何建议?
    • 您可以根据自己的经验学习。我也在从这里专家的 stackoverflow 问题和答案中学习。
    • codeschool(29 美元/月)jQuery 课程级别 1 和 2 提供了学习 AJAX 的讲座练习方法。无论如何,您的问题是 jQuery - 而不是 AJAX。
    猜你喜欢
    • 1970-01-01
    • 2014-11-29
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 2017-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多