Rails - refreshing page instead of partials when using AJAX [duplicate] - javascript

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Rails - AJAX to for new/create action
I have a timeline that has partials for events on it, so you can CRUD events directly on the timeline. I've got the delete part working fine, so that the delete partial and the timeline refresh each time an event gets deleted. However, I can't get it working when a new event is created. Instead of refreshing the form and the timeline, the whole page refreshes.
I'm assuming this is something to do with the controller? But I can't seem to fix it. Any help would be much appreciated, thanks :0)
events controller:
def create
#event = Event.new(params[:event])
respond_to do |format|
if #event.save
format.html { redirect_to #event.timeline, notice: 'Event was successfully created.' }
format.json { render json: #event, status: :created, location: #event }
format.js
else
format.html { render action: "new" }
format.json { render json: #event.errors, status: :unprocessable_entity }
format.js
end
end
end
timeline/show:
<div id="new-event">
<%= render :partial => "new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) }, :remote => true %>
</div>
timeline/_new_event:
<br />
<h2>Add an event</h2>
<h4>Fill in the form and click 'Create Event' to add a new event to the timeline.</h4>
<%= form_for(event) do |f| %>
<% if event.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(event.errors.count, "error") %> prohibited this event from being saved:</h2>
<ul>
<% event.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%=f.hidden_field 'timeline_id', :value => current_user.timeline.id %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :start_date, :order => [:day, :month, :year], :start_year => 1800 %>
</div>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :headline, :size => 50 %>
</div>
<div class="field">
<%= f.label :event_description %><br />
<%= f.text_area :text, :size => "47x4" %>
</div>
<%= check_box_tag "blockCheck", :value => "1", :checked => false %>
<div class="field" id="media_box">
<%= f.label :media %> <span>Please paste a URL here</span><br />
<%= f.text_field :media, :size => 50 %>
</div>
<div class="field">
<%= f.label :media_description %><br />
<%= f.text_area :caption, :size => "47x3" %>
</div>
<div class="actions">
<%= f.submit 'Create Event', :class => "btn btn-success", :remote => true %>
</div>
<% end %>
events/create.js.erb:
$('#new-event').html('<%= escape_javascript( render :partial => "/timelines/new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) } ) %>');
$('.notice').html("<p>Event was successfully created.</p>");
$('.notice').show(300);
$('#my-timeline-box').html('<%= escape_javascript( render :partial => "/timelines/my_timeline" ) %>');
$('#show-timeline').html('<%= escape_javascript( render :partial => "/timelines/show_timeline" ) %>');
(The bottom two lines are to refresh the timeline iteself).
UPDATE:
Here is the error message:
Started POST "/events" for 127.0.0.1 at 2012-10-16 14:52:37 +0100
Processing by EventsController#create as JS
Parameters: {"utf8"=>"V", "authenticity_token"=>"i8oiRI7rOLsfb5o45QCK0te/hAsWv
BMTqpxU9KrbmNA=", "event"=>{"timeline_id"=>"1", "start_date(3i)"=>"16", "start_d
ate(2i)"=>"10", "start_date(1i)"=>"2012", "headline"=>"", "text"=>"", "media"=>"
", "caption"=>""}, "commit"=>"Create Event"}
←[1m←[35m (0.0ms)←[0m begin transaction
←[1m←[36mSQL (5.0ms)←[0m ←[1mINSERT INTO "events" ("caption", "created_at", "
credit", "end_date", "headline", "media", "start_date", "text", "thumbnail", "ti
meline_id", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)←[0m [["capti
on", ""], ["created_at", Tue, 16 Oct 2012 13:52:37 UTC +00:00], ["credit", nil],
["end_date", nil], ["headline", ""], ["media", ""], ["start_date", Tue, 16 Oct
2012], ["text", ""], ["thumbnail", nil], ["timeline_id", 1], ["updated_at", Tue,
16 Oct 2012 13:52:37 UTC +00:00]]
←[1m←[35m (88.0ms)←[0m commit transaction
Rendered events/create.js.erb (99.0ms)
Completed 500 Internal Server Error in 617ms
ActionView::Template::Error (Called id for nil, which would mistakenly be 4 -- i
f you really wanted the id of nil, use object_id):
1: $('#new-event').html('<%= escape_javascript( render :partial => "/timelin
es/new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) } )
%>');
2: $('.notice').html("<p>Event was successfully created.</p>");
3: $('.notice').show(300);
4: $('#my-timeline-box').html('<%= escape_javascript( render :partial => "/t
imelines/my_timeline" ) %>');
app/views/events/create.js.erb:1:in `_app_views_events_create_js_erb___8626901
43_20024148'
app/controllers/events_controller.rb:59:in `create'
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.4.rc1/lib/action_d
ispatch/middleware/templates/rescues/_trace.erb (5.0ms)
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.4.rc1/lib/action_d
ispatch/middleware/templates/rescues/_request_and_response.erb (2.0ms)
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.4.rc1/lib/action_d
ispatch/middleware/templates/rescues/template_error.erb within rescues/layout (1
000.1ms)

You have :remote => true on the submit button. That's incorrect. It should be on the form:
<%= form_for(event, :remote => true) do |f| %>

You have not initialized #timeline in your controller code. Thus you get a nil action.
So, put in your Create code:
#timeline = current_user.timeline

Related

How to avoid sending params of fields deleted using JQuery remove()

In this code I was trying to remove fileds for nested_attributes using ajax :remote => ture to avoid reloading
the whole page in browser. Although fileds in fields_for was removed from DOM and association was removed from database, the fields of the nested attributes
still exist in page source and raise ActiveRecord::RecordNotFound error when trying to send params to update action of parent model
consider the following code:
_artist_form.html.erb
<%= form_for #artist do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br/>
<%= f.label :style %>
<%= f.text_field :style %><br/>
<%= f.fields_for :songs do |song_builder|%>
<div id = 'song_<%= song_builder.object.id %>_div'>
<%= song_builder.label :title %>
<%= song_builder.text_field :title %><br/>
<%= song_builder.label :lyrics %>
<%= song_builder.text_area :lyrics %><br/>
<%= link_to 'Remove song', delete_song_path(:a_id => #artist.id, :s_id => song_builder.object.id),
:method => :delete , :remote => true %>
</div>
<% end %>
<%= f.submit 'Save' %>
<% end %>
routes.rb
Rails.application.routes.draw do
...
delete '/artists/remove_song', :to => 'artists#delete_song', :as => :delete_song
end
application_controller.rb
class ArtistsController < ApplicationController
def edit
...
end
def update
#artist = Artist.find(params[:id])
if #artist.update(artist_params) #=> error Couldn't find Song with ID=2 for Artist with ID=2
redirect_to artist_path(#artist)
else
flash[:errors] = #artist.errors.full_messages
render :edit
end
end
...
def delete_song
#song_id = params[s_id]
aritst = Artist.find(:params[a_id])
song = artist.songs.find(#song_id)
song.delete
respond_to do |format|
format.js {render 'delete_song.js.erb'}
end
end
end
delete_song.js.erb
$('#song_<%= #song_id %>_div').remove() ;
Error
Couldn't find Song with ID=2 for Artist with ID=2
how to prevent sending params of removed fields by $(...).remove() to update action?
I tried to find a solution for this error. So according to charlietfl comment, I tried to store delete status somewhere locally, then rails can delete association later. So I modified the code as following:
deleting all remote script code including delete_song.js.erb file and delete_song action and delete route. then I allowed marking nested attribute for delete in Artist model file:
accepts_nested_attributes_for :songs, :allow_destroy => true
then adding delete button in _artist_form.html.erb file as following:
<%= button_tag 'x' , :class => 'close_sign', :type => 'button', :onclick => "$('#song_#{song_builder.object.id}_destroy').val('true'); $('#song_#{song_builder.object.id}_div').hide()" %><br/>
and a hidden flied to fields_for as below:
<%= song_builder.hidden_field :_destroy, :id => "song_#{song_builder.object.id}_destroy" %>
and allowing :songs_nested_attributes => [:title, :lyrics, :_destroy] in song_params
once user remove the song field, it will be hidden and marked for destroy later

Why is the link_to submitting form twice?

I am trying to use JavaScript with jquery in rails to update a div without reloading the page. Its working but the comment is being created twice. I know something is wrong in the form partial but couldn't figure it out. Any help?
The following are the files -
_new_comment.html.erb
<%= form_for [:home, Comment.new], :url => home_comments_path, :html => {:id => "comment-new-" + post.id.to_s} do |f| %>
<div>
<%= f.text_area :message, :class => "message-area-" + post.id.to_s, :placeholder => "Add comment..." %>
<%= f.hidden_field :post_id, :value => post.id %>
<span class="new-comment"><%= link_to 'Add', '#', remote: true, :onclick => "$('#comment-new-#{post.id}').submit()" %></span>
</div>
<% end %>
comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
if #comment.save
flash[:notice] = 'Comment added sucessfully'
respond_to do |format|
format.html { redirect_to home_posts_url }
format.js
end
end
end
create.js.erb
$("#comment-new-83").before('<div class="notice"><%= escape_javascript(flash[:notice]) %></div>');
$("#comment-new-83")[0].reset();
home.js
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
$(document).ready(function() {
$("#comment-new-83").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false;
})
})
form_for will automatically post to the controller. You need not submit the form explicitly using jquery.
Reference

undefined method `item_path' while working with ajax

Im trying to update my create item action to work with Ajax but Im getting an error of undefined methoditem_path` which i wasn't getting before when it was responding in regular html format. The item is created and saved but ajax doesn't seem to work properly though.
Here is my _from partial :
<%= form_for [#user, item], remote: true do |f|%>
<div class="form-group">
<%= f.label :name, class: 'sr-only' %>
<%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
</div>
<%= f.submit "Submit Item", class: 'btn btn-primary pull-right' %>
<% end %>
item#create:
def create
#item = Item.new(item_params)
#item.user = current_user
if #item.save
flash[:notice] = 'Item saved successfully.'
else
flash[:alert] = 'Item not saved. Title is too short or missing. Please try again.'
end
respond_to do |format|
format.html
format.js
end
end
create.js.erb:
$('.js-items').prepend("<%= escape_javascript(render(#item)) %>");
$('.new-item').html("<%= escape_javascript(render partial: 'items/form', locals: {user: #user , item: #item }) %>");
User#show view
<div class='new_item'>
<%= render :partial => 'items/form', :locals =>{:item => Item.new , :user => #user} %>
</div>
<div class='js-items'>
<%= render #user.items %>
</div>
routes:
user_items GET /users/:user_id/items(.:format) items#index
POST /users/:user_id/items(.:format) items#create
new_user_item GET /users/:user_id/items/new(.:format) items#new
edit_user_item GET /users/:user_id/items/:id/edit(.:format) items#edit
user_item GET /users/:user_id/items/:id(.:format) items#show
PATCH /users/:user_id/items/:id(.:format) items#update
PUT /users/:user_id/items/:id(.:format) items#update
DELETE /users/:user_id/items/:id(.:format) items#destroy
The error im getting in rails s :
ActionView::Template::Error (undefined method `item_path' for #<#<Class:0x007fa4f0d30cd8>:0x007fa4f31b26b0>):
1: <%= form_for [#user, item], remote: true do |f|%>
2: <div class="form-group">
3: <%= f.label :name, class: 'sr-only' %>
4: <%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
app/views/items/_form.html.erb:1:in `_app_views_items__form_html_erb__331698480542899910_70173200751480'
app/views/items/create.js.erb:2:in `_app_views_items_create_js_erb___3618987352886002527_70173200313760'
app/controllers/items_controller.rb:17:in `create'
Do something like that.
<%= form_for [#user, item], user_items, remote: true do |f|%>
If it doesn't work then run
rake routes
in terminal see what's your path.

Passing Form object when using Ajax in rails

I have a complex form for a survey. A survey
belongs_to :template
has_many :questions, :through => :template
has_many :answers, :through => :questions
I.e. User creates a new survey, and he must select a survey template. The survey template will create some default questions and answer fields.
<%= form_for #survey do |f| %>
<p>Select a template:</p>
<%= render #templates, :locals => {:patient => #patient }, :f => f %>
<% end %>
Then I render the _templates partial, and I still have access to the form object. From here, the idea is that a user can click on a template name, and the template questions and answers will be rendered via Ajax.
<% #templates.each do |template| %>
<div class="thumbnail">
<%= link_to template.name,
{ :controller => "surveys",
:action => "new",
:template_id => template.id,
:patient_id => nil,
:f => f,
:remote=> true },
:class=> "template", :id=> template.id %>
</div>
<% end %>
surveys#new:
respond_to :js, :html
def new
#template = Template.find(params[:template_id])
#patient = Patient.find(params[:patient_id])
end
new.js.erb:
$('#assessment').append("<%= j (render new_survey_path, :locals => {:f => f} ) %>");
new_survey_path:
<%= f.fields_for :questions do |builder| %>
<% #template.questions.where(category:"S").each do |question| %>
<p><%= question.content %></p>
<%= render 'answer_fields', :question=> question %>
<% end %>
<% end %>
But I'm having trouble passing the original |f| object from #survey to new_survey_path. The last place I can access the form object is in the templates partial.
How can I fix this?

Radio buttons not changing database in firefox but they do in chrome, why?

I have a remote form which contains 3 radio button tags, each will change the DB accordingly. This works perfectly fine in chrome but when I switch to FF the radio get checked and all but the DB does not change at all.
This is the form in my view.
<%= form_tag ("deal_status"), :remote => true, :class => "deals_status" do %>
<%= hidden_field_tag 'deal_id', d.id.to_s %>
<%= radio_button_tag( :state, "won"+d.id.to_s, d.state == "won", :class => "toggle-btn-left toggle-btn", :value =>"won") %>
<%= label_tag 'state_won'+d.id.to_s, "won", :class=>"btn" %>
<%= radio_button_tag :state, "lost"+d.id.to_s, d.state == 'lost', :class => "toggle-btn-center toggle-btn",:value => "lost" %>
<%= label_tag 'state_lost'+d.id.to_s, "lost",:class=>"btn" %>
<%= radio_button_tag :state, "pending"+d.id.to_s, d.state == 'pending',:class => "toggle-btn-right toggle-btn", :value => "pending" %>
<%= label_tag 'state_pending'+d.id.to_s, "pending",:class=>"btn" %>
<% end %>
this the js that does the submitting
$("body").on("change", "form :radio", function(){
$(this).closest("form").submit();
});
and this is the controller's action :
def deal_status
deal_id = params[:deal_id]
d = Deal.find_by_id(deal_id)
d.state = params[:state]
d.save
#deal_id = deal_id
#deal = d
respond_to do |format|
format.js
end
end

Categories

Resources