Rails 4 Ajax在每次提交时都会在同一页面上多次呈现

时间:2014-10-09 00:12:46

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

每次我在我的rails应用程序中点击提交时,它都会发送请求2次。我可以通过点击刷新摆脱第二部分。这是一个嵌套的应用程序。 Todo has_many项目。我包括控制器和创建和部分。 我添加了一张照片以使其更加清晰。 enter image description here

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 %>

来自控制台的更多信息。它从我点击列表(Groceries)开始,然后我点击提交添加项目

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)

1 个答案:

答案 0 :(得分:0)

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

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

在此代码中,您是todo-items中预先挂起的html,您应该每次都替换项目。如下所示:

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

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