基于AJAX请求的Rails更新元素?

时间:2019-05-29 03:39:28

标签: javascript ruby-on-rails ajax

我已经阅读了很多有关Rails和AJAX和5.1 Unobtrusive javascript的文章。例如,它以.js文件解释了许多有关响应Rails版本的AJAX调用的信息。

但是,我要执行的操作不是提供整个.js文件,它只是在<% link_to %> POST请求之后更新一个元素。据我了解,设置remote: true将其作为AJAX请求提交。

基本上,我有一个“帖子”,用户可以通过链接的“喜欢”按钮来喜欢。这会将POST请求发送到“帖子”控制器,该控制器将帖子更新为喜欢,并在帖子中添加喜欢的内容。

不幸的是,您需要刷新页面才能看到喜欢的帖子的效果(这只是链接会更改颜色以及超棒的字体图标)。我基本上是希望更新而不需要刷新。

我根据所读内容进行“思考”,我需要制作一个respond do并通过.js在要更新的视图中以.js文件响应请求(例如,如果控制器操作称为“喜欢”,可能是视图中的like.js.erb文件正在更新?)。但是我不想提供整个新页面。或者只是运行.js?

那我可以做类似$('i.fa-icon#id').style.color = "blue"之类的事情吗? (假设我可以将数据从控制器发送到.js.erb文件?)。不确定执行此操作的最佳方法,请不要经常将元素设置为data-attribute之类的东西(我仍然是初学者)。

2 个答案:

答案 0 :(得分:2)

您的描述是正确的! 与另一个答案相反,您甚至不需要事件侦听器,但正如您所说的那样,您想在控制器中使用respond_to。 因此,从html开始:

# post/index.html.erb
<div id="like-button">
  <%= button_to "Like this post", post_path(@post), remote: true %>
</div>

请注意,当您使用button_to助手时,默认情况下它将是POST请求。

如果单击它,它将转到您要更改为的controller#update

#posts_controller.rb
...
def update
  @post.save
    respond_to do |format|
      format.html { redirect_to post_path(@post) } 
      format.js  # <-- will render `app/views/posts/update.js.erb`
    end
end

注意:format.html在禁用JS时呈现。 现在,在启用JS的情况下,它将执行app/views/posts/update.js.erb文件。看起来可能像这样:

const likeButton = document.getElementById('like-button');
likeButton.innerHTML = '<%= j render "posts/liked-link", post: @post %>';

最后一行在做什么?当然,您可以直接使用JavaScript更改样式,但是也可以呈现新的局部样式-这将在新的html文件中创建:

# app/views/posts/liked_link.html.erb
<div id="like-button ">
 <p>"You liked this post!" </p>
</div>

我现在只是将链接/按钮更改为p,但是您当然可以做任何想做的事情。

希望如此:)

答案 1 :(得分:1)

不确定我是否理解问题,但是是否要像按钮一样进行更新:

您想要做的是向按钮添加一个事件侦听器,并在单击该按钮时向处理喜欢(具有正确参数)的任何路由发出POST请求,并且您的控制器应使用“喜欢”对象(或任何其他对象)进行响应在数据库中存储)。让您对成功方法发表请求,以抓住“赞”按钮并将其更改为您想要的外观

$(“#like-btn”).click(function(){ 
Rails.ajax({
  url: "/some/url/to/like/controller",
  type: "post",
 data: [your post data],
  success: function(data) { $(`#${ data[“btn-name”] }`).attr(“color”, “blue”; }
})    
}

您可以将此脚本粘贴在html页面底部

您不必完全像这样进行操作,只是让您了解如何设置让JavaScript和Ajax处理发布请求和更新前端的模式,而不是使用html按钮