Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ajax on rails 4

I have an app that allows users to like a post. When someone likes the post, the post request works but the view isn't updated unless I refresh the page. I'm stuck on this one. This is what I have so far:

Javascript

$('.favorite').on('click', function() {
  var $heart = $(this).find('.fa');
  $heart.removeClass('fa-heart-o').addClass('fa-heart');
  // POST request to server to create favorite in db
  $.post('/favorites', {
    favorite: { post_id: $(this).attr('data-id') }
  },
  function(data) {
    console.log(data);
  });
});

The controller

def create
  post = Post.find_by_id(favorite_params[:post_id])
  if current_user.favorite_posts.include? post
    render json: {}, status: :bad_request
  else
    @favorite = current_user.favorites.new(favorite_params)
    if @favorite.save
      render json: @favorite
    else
      render json: { errors: @favorite.errors.full_messages }, status: :unprocessable_entity
  end
end

end

This is the view

<% if current_user.favorite_posts.include? post %>
  <span class="fa fa-heart"> <%= post.favorites.count %></span>
<% else %>
  <span class="fa fa-heart-o"> <%= post.favorites.count %></span>
<% end %>

Any help is appreciated. Thanks.

like image 691
robb Avatar asked Dec 24 '22 14:12

robb


2 Answers

Do this:-

var new_count;
new_count = function() {
  # your script
};



$(document).ready(new_count);
$(document).on('page:load', new_count);

This issue seems due to turbolink checkthis

like image 89
Arvind Avatar answered Jan 12 '23 16:01

Arvind


There are two solutions to this:

  1. Invoke the view change with your in-browser ajax
  2. Use the Rails UJS functionality to run the view change on the server

I think your biggest problem is you don't have any functionality to change your view upon a successful request. The two options above are what you have to get it working, so I'll detail them for you here:


Ajax

Ajax will send a request for you; you still have to manage its response & functionality:

$.post('/favorites', { favorite: { post_id: $(this).attr('data-id') }},
.done( function(data) {
  /* Manipulate your view here */
  $("span.fa").text(data);
  console.log("Success");
});

You must remember that Ajax is just an asynchronous request. That is, Javascript will act like a micro-browser, sending data to the server on your behalf.

It will then receive a response from the server (presumably containing the data you want)... it's your job to then manipulate your view with this data.


JS

The other method you could use involves the Rails UJS system. That is, you can fire javascript ERB templates after your controller action is fired.

This would give you the ability to manipulate your view as you need, without editing your current javascript:

$.post('/favorites', { favorite: { post_id: $(this).attr('data-id') }}
  .done( function(data) { console.log(data); });


#app/controllers/favourites_controller.rb
class FavouritesController < ApplicationController
   def create
     ...
     respond_to do |format|
        if @favorite.save
          format.js #-> invokes /views/favourites/create.js.erb
          format.json { render json: @favorite }
        else
          format.js
          format.json { render json: { errors: @favorite.errors.full_messages }, status: :unprocessable_entity }
  end
end

You'll then be able to use app/views/favourites/create.js.erb to manipulate your view:

#app/views/favourites/create.js.erb
$("span.fa").hide();
like image 31
Richard Peck Avatar answered Jan 12 '23 17:01

Richard Peck