Ajax 和 Rails 4:创建实例变量并更新视图而不刷新

Posted

技术标签:

【中文标题】Ajax 和 Rails 4:创建实例变量并更新视图而不刷新【英文标题】:Ajax and Rails 4: Create instance variable and update view without refresh 【发布时间】:2017-12-20 03:32:13 【问题描述】:

我有一个coaching_notes 索引的一部分,其中包含一个用于创建笔记的表格。我想创建一个指导说明并在不刷新页面的情况下进行部分更新。我收到一个未知操作错误:找不到 CoachingNotesController 的操作“显示”。如果我添加 show 操作,我会收到缺少模板的错误。当我尝试从控制器中删除 format.html 部分时,我也遇到了未知格式错误。

我在 Rails 文档之后对我的代码进行了建模,并且还查看了一堆类似的情况,但无法让它工作。

非常感谢任何帮助!!!

/views/coaching_notes/_index.html.erb

<div id="coaching_notes">
  <% @coaching_notes.each do |note| %>
    <li> <%= note.content %> </li>
  <% end %>
</div>
<br>
<% @coaching_note = CoachingNote.new(user_id: current_user.id, meeting_id: session[:current_meeting_id]) %>
<%= form_for(@coaching_note, remote: true) do |f| %>

  <%= f.hidden_field :user_id %>
  <%= f.hidden_field :meeting_id %>
  <%= f.hidden_field :archive %>
  <%= f.text_field :content %>

  <%= f.submit %>
<% end %>

/views/coaching_notes/_coaching_note.html.erb

<li><%= note.content %></li>

/views/coaching_notes/create.js.erb

$("<%= escape_javascript(render coaching_note) %>").appendTo("#coaching_notes");

/controllers/coaching_notes_controller.rb

def create
@coaching_note = CoachingNote.new(coaching_note_params)

respond_to do |format|
  if @coaching_note.save
    format.html  redirect_to @coaching_note, notice: 'note was successfully created.' 
    format.js   
    format.json  render json: @coaching_note, status: :created, location: @coaching_note 
  else
    format.html  render action: "new" 
    format.json  render json: @coaching_note.errors, status: :unprocessable_entity 
  end
end

routes.rb

resources :coaching_notes

2017 年 7 月 15 日更新 - 我根据@Cira 的回答修改了几个文件:

/views/coaching_notes/_index.html.erb

<div id="coaching_notes">
  <% @coaching_notes.each do |note| %>
    <li> <%= note.content %> </li>
    <%= link_to "delete", note, :remote => true, :method => :delete, :data => :confirm => "Are you sure?" %>
  <% end %>
</div>
<br>
<% @coaching_note = CoachingNote.new(user_id: current_user.id, meeting_id: session[:current_meeting_id]) %>
<%= form_for(@coaching_note, remote: true) do |f| %>

  <%= f.hidden_field :user_id, id: 'user' %>
  <%= f.hidden_field :meeting_id, id: 'meet' %>
  <%= f.hidden_field :archive, id: 'arch' %>
  <%= f.text_field :content, id: 'content' %>

  <%= f.submit 'Add note', id: 'submit_note' %>
<% end %>

// newly added
<script>
$('#submit_note').on( "click", function() 
  var u = $('#user').val()
  var m = $('#meet').val()
  var a = $('#arch').val()
  var c = $('#content').val()

  $.ajax(
    url: "/coaching_notes/create",
    type: "POST",
    data: 
      user_id: u,
      meeting_id: m,
      archive: a,
      content: c
    ,
    dataType: "json",
    success: function(info) 
      $('#coaching_notes').data( "html", info )
    
  );
)
</script>

(我不知道的主要部分是带有数据属性的成功函数)

/controllers/coaching_notes_controller.rb

def create
    @coaching_note = CoachingNote.new(coaching_note_params)

    @html = render_to_string :partial => "coaching_notes/index"
    respond_to do |format|
      if @coaching_note.save
        format.html
        format.json  render json: "html" => @html 
      else
        format.html  render action: "new" 
        format.json  render json: @coaching_note.errors, status: :unprocessable_entity 
      end
    end

两件事: 1. 我的成功函数在 ajax 中看起来正确吗? 2. 需要在控制器中输入if @coaching_note.save吗?

我现在得到的错误是'NoMethodError in CoachingNotes#create - undefined method `each' for nil:NilClass' 在coaching_notes/index.html 中突出显示这一行

<% @coaching_notes.each do |note| %>

然后我得到“缺少模板 coaching_notes/index”

我觉得我们越来越近了!任何帮助表示赞赏!

【问题讨论】:

【参考方案1】:

我认为您可以做的可能是当用户按下提交按钮时,通过 AJAX 将表单的数据传递到控制器操作(创建)

$.ajax(
                    url: "/coaching_notes/create",
                    type: "POST",
                    data: a hash of the data retrieved from the inputs,
                    dataType: "json",
                    success: function(data) 
                        //replace data of div you want here using String(data["html"], html being the attribute passed back via json from the controller.
                    
                );

在你的控制器中创建你的指导笔记后再次渲染部分,如下所示:

@html = render_to_string :partial => "coaching_notes/index"
      respond_to do |format|
        format.html
        format.json render json: "html" => @html
      end

并使用 AJAX 将 HTML 发送回视图,并在 ajax 成功功能下替换教练笔记的原始 div 的 HTML。

干杯!

【讨论】:

感谢@Cira,我还没有让它工作,但我更新了我的更改供您查看。我非常感谢您的帮助! AJAX中的success属性是指只有AJAX调用成功时才执行成功功能,我认为data是你必须放的参数而不是info。同样对于您的coaching_notes,我认为应该没有s,因为您的变量名称是coaching_note。我也不太清楚为什么你的索引是部分的,也许创建另一个文件作为部分并使索引不是部分的?【参考方案2】:

原来问题是我在 application.js 中遗漏了这行代码:

 //= require jquery_ujs

对于那些不知道的人,ujs 代表“Unobtrusive JavaScript”。如果不需要这个,remote: true 不会有太大帮助。

在弄清楚这一点之前,我确实找到了只使用 javascript 和 ajax 的解决方案,这是删除笔记的脚本:

$("input[value='Del']").click(function(event)
  event.preventDefault();
  var num = this.id
    $.ajax(
        type: "DELETE",
        url: "/coaching_notes/" + this.id,
        dataType: "json",
        success: function(data)
          // remove the div containing the note
        
    );
);

请注意,您需要使用preventDefault() 来阻止表单提交。

添加注释的脚本肯定可以重构更多但仍然有效:

$(document.body).delegate('input:text', 'keypress', function(e) 
    // if user hits enter key
    if (e.which === 13) 
        e.preventDefault();
      createNote()
    
)

$("#submit_note").click(function(e) 
  e.preventDefault()
  createNote()
)

function createNote() 
  var u = $('#user').val()
  var m = $('#meet').val()
  var a = $('#arch').val()
  var c = $('#content').val()

  if (c != "") 
    $.ajax(
      url: "/coaching_notes",
      type: "POST",
      data: 
        "coaching_note": 
          "user_id": u,
          "meeting_id": m,
          "archive": a,
          "content": c
        
      ,
      dataType: "json",
      success: function(note) 
        $("#content").val('') // clears the input box
        // add the new note here
      
    );
  
 

关于委派按键的部分是当用户按下“输入”键时发送注释。同样,e.preventDefault() 阻止表单通过 Rails 提交。

希望这对其他人有帮助!我知道我被困了一段时间,这是一个非常容易解决的问题。不要忘记! 确保你的 APPLICATION.JS 中有这个!

 //= require jquery_ujs

谢谢

【讨论】:

以上是关于Ajax 和 Rails 4:创建实例变量并更新视图而不刷新的主要内容,如果未能解决你的问题,请参考以下文章

AJAX 日历更新页面 rails 4

Rails/Ajax 在提交后将表单从创建更改为更新

Rails 4 - 通过使用 AJAX UJS 的集合中的链接更新表

Rails 4 引发 ArgumentError(参数数量错误(2 对 1)):通过 AJAX POST 更新时

Ruby on Rails 复选框未在提交表单时更新

Rails 4:如何使用 AJAX 上传文件