Note that there are some explanatory texts on larger screens.

plurals
  1. PORails/Ajax change form from create to update after submission
    text
    copied!<p>So I wanted to play with a star ratings page, where I have 5 rating questions and you can rate once (create) and update your rating at any given time. The rating form is ajaxified but the problem is the form element stays as a Create method after submission instead of an update method.</p> <p>I followed a pretty cool tutorial by <a href="http://eighty-b.tumblr.com/post/1569674815/creating-an-ajaxified-star-rating-system-in-rails-3" rel="nofollow">eighty-b</a> but there is one part that is missing about the form being updated to the proper method.</p> <p>Here is the code</p> <p>I have a form in a partial <code>rating_questions/_quick_form.html.erb</code> with a nested form for each rating form. Note that the form route is using a helper to define if it should be a create or and update action</p> <pre><code>&lt;div class="rating_questions"&gt; &lt;% @rating_questions.each do |rating_question| %&gt; &lt;%= render partial: "rating_questions/rating_form", :locals =&gt; {:rating_question =&gt; rating_question} %&gt; &lt;% end %&gt; &lt;/div&gt; </code></pre> <p>The <code>rating_form.html.erb</code> partial</p> <pre><code># EDIT: I added the temporary random id in an instance variable to make sure the form id and hidden_field have the same reference &lt;% @rand_id = SecureRandom.hex %&gt; &lt;%= form_for(rating_ballot(rating_question), :remote =&gt; true, :html =&gt; { :class =&gt; 'rating_ballot', :id =&gt; @rand_id}) do |f| %&gt; &lt;div class="rq"&gt;&lt;%= rating_question.title %&gt;&lt;/div&gt; &lt;%= hidden_field_tag :temp_id, @rand_id %&gt; &lt;%= f.label("value_#{rating_question.id}_1", content_tag(:span, '1'), {:class =&gt; "rating", :id =&gt; "1"}) %&gt; &lt;%= radio_button_tag("rating[value]", 1, current_user_rating(rating_question) == 1, :class =&gt; 'radio_button', :id =&gt; "rating_value_#{rating_question.id}_1") %&gt; ... (the other rating radio buttons) ... &lt;%= f.hidden_field("rating_question_id", :value =&gt; rating_question.id) %&gt; &lt;%= f.submit :Submit, :id =&gt; "rating_submit" %&gt; &lt;% end %&gt; </code></pre> <p>Then in my <code>create.js.erb</code> I added the line to replace the form with the partial</p> <pre><code>$('#&lt;%= params[:temp_id] %&gt;').replaceWith("&lt;%= j render(partial: 'rating_questions/rating_form', locals: {:rating_question =&gt; @rating_question}) %&gt;"); </code></pre> <p>The helper methods for defining if the form should be a create or an update if there is an existing record</p> <pre><code>def rating_ballot(rating_question) if @rating = current_user.ratings.find_by_rating_question_id(rating_question.id) [rating_question, @rating] else [rating_question, current_user.ratings.new] end end def current_user_rating(rating_question) if @rating = current_user.ratings.find_by_rating_question_id(rating_question.id) @rating.value else "N/A" end end </code></pre> <p>and my <code>ratings_controller.rb</code> that calls for <code>create.js.erb</code> and <code>update.js.erb</code></p> <pre><code>def create @rating_question = RatingQuestion.find_by_id(params[:rating_question_id]) @rating = Rating.new(params[:rating]) @rating.user_id = current_user.id if @rating.save respond_to do |format| format.html { redirect_to rating_questions_path, :notice =&gt; "Your rating has been saved"} format.js end end end def update @rating_question = RatingQuestion.find_by_id(params[:rating_question_id]) @rating = current_user.ratings.find_by_rating_question_id(@rating_question.id) if @rating.update_attributes(params[:rating]) respond_to do |format| format.html { redirect_to rating_questions_path, :notice =&gt; "Your rating has been updated"} format.js end end end </code></pre> <p>Obviously I only want to update the form that was just submitted and not the other ones. Any idea on how to reload the form with the proper method using Javascript in the create.js.erb and the update.js.erb?</p> <p>Thank you very much!</p> <p><strong>EDIT ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</strong> (See the edits above)</p> <p>I went ahead with your suggestions and I added the random id to the form and changed the create.js.erb, but I encountered problems:</p> <p>1) After the ratings forms are replaced, the Javascript no longer works on that partial. </p> <p>Here is also the coffee script for dynamic interactions of the stars (actually the form radio labels)</p> <pre><code>$ -&gt; # Add the "Bright class" to the stars for each checked radio button before the document is ready. $("form.rating_ballot").each -&gt; checkedId = undefined checkedId = $(this).find("input:checked").attr("id") $(this).find("label[for=" + checkedId + "]").prevAll().andSelf().addClass "bright" $(document).ready -&gt; # makes stars glow on hover. $("form.rating_ballot &gt; label").hover (-&gt; # mouseover $(this).prevAll().andSelf().addClass "glow" ), -&gt; # mouseout $(this).siblings().andSelf().removeClass "glow" # makes stars stay glowing after click. $("form.rating_ballot &gt; label").click -&gt; $(this).siblings().removeClass "bright" $(this).prevAll().andSelf().addClass "bright" # Submits the form (saves data) after user makes a change. $(".rating_ballot").change -&gt; $(this).submit() </code></pre> <p><strong>EDIT 2 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</strong> The fact that the update action was submitting all the form was corrected.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload