Rails beginner
Rails beginner

Reputation: 14504

Rails How to create ajax star rating

I am trying to create some simple ajax rating using rate it jquery . I am able to see the stars and press them. But my form does not submit.

How do I submit the rating with ajax?

In my table I have two columns:

rating_score => The current score
ratings => The number of ratings which led to the score

My kategori show view:

<h1><%= @kategori.h2.force_encoding("UTF-8") %></h1>
<div id="konkurrancer"><%= render 'konkurrencer', :remote => true %></div>

My konkurrencer partial:

<div id="tabel">
  <table id="tabel1">
    <tr id="toptr">
      <td><%= sortable "name", "Navn" %></td>
    </tr>
    <% @konkurrancer.each do |vind| %>
      <tr class="thumbnail-item" onclick="window.open('<%= vind.tracking %>')">
        <td><%= truncate(vind.name.force_encoding("UTF-8"), :length => 45) %></td>
        <td>
          <div id="container">
            <%= render :partial => "rating", :remote => true, :locals => { :vind => vind } %>
          </div>
        </td>
      </tr>
    <% end %>
  </table>
  <div id="pagenavi">
    <%= hidden_field_tag :direction, params[:direction] %>
    <%= hidden_field_tag :sort, params[:sort] %>
  </div>
</div>

My ratings partial:

<%= form_for(:vind, :url => rate_path(vind.id), :remote => true, :html => { :method => 'put', :id => "rateform"}) do |f| %>
<%= f.text_field :ratings, :size => 1, :min => 1, :max => 6, :value => 1, :type => 'range', :step => '1', :id => "#{vind.id}" %>
<div class="rateit" id="rateit10b" data-rateit-backingfld="#<%= vind.id %>" data-rateit-resetable="false" ></div>
<% end %>
  <script type ="text/javascript">
     $('.rateit').bind('rated reset', function (e) {
         var ri = $(this);

         //if the use pressed reset, it will get value: 0 (to be compatible with the HTML range control), we could check if e.type == 'reset', and then set the value to  null .
         var value = ri.rateit('value');
         var frmurl = ri.closest('form').attr('action'); //get the url from the form

         $.ajax({
             url: frmurl, //your server side script
             data: { ratings: value }, //our data
             type: 'PUT',
             success: function (data) {
                  //write here something when everything went ok

             },
             error: function (jxhr, msg, err) {
                 alert(msg); //something went wrong.
             }
         });
     });
 </script>

My rate.js:

$('#<%= @container %>').html('<%= escape_javascript(render(partial: 'rating', locals: { konkurrancer: @konkurrancer })) %>');

My Controller:

class KonkurrancersController < ApplicationController
  def rate
    @konkurrancer = Konkurrancer.find(params[:id])
    @container = "Konkurrancer"[email protected]_s

    @theme.rating_score += params[:rating].to_i
    @theme.ratings += 1
    @theme.save

    respond_to do |format|
      format.js
    end
  end
end

Here is my rating in my browser. When I press gem Vind the params rating is send with ajax with the value 5. The problem is that I want it to send when pressed on the stars instead using the submit button. enter image description here

My console when the form is submitted:

Started POST "/konkurrancers/rate/12" for 127.0.0.1 at 2011-04-04 23:37:56 +0200

  Processing by KonkurrancersController#rate as JS
  Parameters: {"utf8"=>"Ô£ô", "authenticity_token"=>"3IqZ6IfvaFYQnVeMYu2a09PcCnm
VW52vaEp2KjfJ1g8=", "vind"=>{"rating"=>"6"}, "commit"=>"Gem Vind", "id"=>"12"}
  ←[1m←[35mKonkurrancer Load (1.0ms)←[0m  SELECT `konkurrancers`.* FROM `konkurr
ancers`
  ←[1m←[36mCACHE (0.0ms)←[0m  ←[1mSELECT `konkurrancers`.* FROM `konkurrancers`←
[0m
  ←[1m←[35mCACHE (0.0ms)←[0m  SELECT `konkurrancers`.* FROM `konkurrancers`
  ←[1m←[36mKonkurrancer Load (1.0ms)←[0m  ←[1mSELECT `konkurrancers`.* FROM `kon
kurrancers` WHERE (`konkurrancers`.`cached_slug` = '12') LIMIT 1←[0m
  ←[1m←[35mSQL (1.0ms)←[0m  SELECT sluggable_id FROM slugs WHERE ((slugs.sluggab
le_type = 'Konkurrancer' AND slugs.name = '12' AND slugs.sequence = 1))
  ←[1m←[36mKonkurrancer Load (0.0ms)←[0m  ←[1mSELECT `konkurrancers`.* FROM `kon
kurrancers` WHERE (`konkurrancers`.`id` = 12) LIMIT 1←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  BEGIN
  ←[1m←[36mSlug Load (22.0ms)←[0m  ←[1mSELECT `slugs`.* FROM `slugs` WHERE (`slu
gs`.sluggable_id = 12 AND `slugs`.sluggable_type = 'Konkurrancer') ORDER BY id D
ESC LIMIT 1←[0m
  ←[1m←[35mAREL (14.0ms)←[0m  UPDATE `konkurrancers` SET `rating_score` = 17, `r
atings` = 5, `updated_at` = '2011-04-04 21:37:57' WHERE (`konkurrancers`.`id` =
12)
  ←[1m←[36mSQL (16.0ms)←[0m  ←[1mCOMMIT←[0m
Rendered konkurrancers/_rating.html.erb (1.0ms)
Rendered konkurrancers/rate.js.erb (24.0ms)
Completed 200 OK in 439ms (Views: 226.0ms | ActiveRecord: 55.0ms)

My html in view: http://pastie.org/1756195

Upvotes: 1

Views: 1840

Answers (1)

Gideon
Gideon

Reputation: 18491

I'm the author of the RateIt plugin. I have a small clue about Ruby On Rails, but I'll try to answer the question as good as possible.

The RateIt control doesn't submit automatically when something gets rated. You have to bind to the rated event.

If your form is setup correctly, the following Javascript should work:

AJAX submission:

<script type ="text/javascript">
     jQuery('.rateit').bind('rated reset', function (e) {
         var ri = jQuery(this);

         //disable voting...
         ri.rateit('readonly', true); 
         //add a span with the selected rating after the rateit plugin.
         ri.after('<span class="rating">' + ri.rateit('value') + '</span>');

         //if the use pressed reset, it will get value: 0 (to be compatible with the HTML range control), we could check if e.type == 'reset', and then set the value to  null .
         var frm = ri.closest('form');

         jQuery.ajax({
             url: frm.attr('action'), //your server side script
             data: frm.serialize(), //our data
             type: 'POST',
             success: function (data) {
                  //write here something when everything went ok

             },
             error: function (jxhr, msg, err) {
                 alert(msg); //something went wrong.
             }
         });
     });
 </script>

non-AJAX submission

 <script type ="text/javascript">
     jQuery('.rateit').bind('rated reset', function (e) {
         jQuery(this).closest('form').submit();
     });
 </script>

Upvotes: 6

Related Questions