Form_for doesn't work with JS/JQuery - javascript

I have problems getting a form to work when I use JavaScript with it.
Without the remote option set to true all works fine but as soon as I
set it, change the controller and create the needed JS files it produces an
POST .. 500 Internal Server Error
when clicking on the submit button.
Furthermore the reply-preview shows me a Rails Error Page saying
NoMethodError in Vocabs#create and undefined method > for nil:NilClass
in a related partial (which works fine before using JS)
The form (vocabs/_new_form.html.erb) looks like this:
<%= form_for #vocab, remote: true do |f| %>
<%= render 'fields', f: f %>
<%= f.submit "Add", class: "btn btn-large btn-primary" %>
<% end %>
The vocab_controller's create action like this:
def create
#user = current_user
#vocab = current_user.vocabs.build(vocab_params)
#vocabs = #user.vocabs.paginate(page: params[:page])
respond_to do |format|
format.html {
if #vocab.save
flash.now[:success] = "Vocab created!"
redirect_to root_url
else
flash.now[:error] = "Vocab not saved!"
render 'new'
end
}
format.js
end
end
The create.js.erb like this:
$('#new_vocab').remove();
Of course I want to do more than just to remove the form but as I didn't even manage to do that I wanted to keep it simple.
_fields.html.erb:
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.label :nl_word, #user.native_language %>
<%= f.text_field :nl_word %>
<%= f.label :fl_word, #user.foreign_language %>
<%= f.text_field :fl_word %>
<%= f.label :tag, "Your Tag" %>
<%= f.text_field :tag%>
<%= f.label :importance, "Importance" %>
<%= f.select(:importance, options_for_select(
StaticData::IMPORTANCE_SEED, :selected => f.object.importance)) %>
</div>
I hope I could explain myself good enough to get some help here. I tried for hours to find the solution to the problem myself and was looking for similar questions here without finding any and without getting anywhere.

With the help of a friend I found out that the main problem was that I didn't provide any validation for the vocab object i wanted to create in the form (_new_form.html.erb), when processing it with JS.
So I changed the vocab_controller.rb to
def create
#user = current_user
#vocab = current_user.vocabs.build(vocab_params)
#vocabs = #user.vocabs.paginate(page: params[:page])
respond_to do |format|
if #vocab.save
flash.now[:success] = "Vocab created!"
format.html do
redirect_to root_url
end
format.js
else
flash.now[:error] = "Vocab not saved!"
format.html do
render 'new'
end
format.js
end
end
end
That does the trick, and my form works with JS now.

Related

Rails AJAX Destroy - Re-render index issues

I have an issue with a Rails AJAX app which is confusing me, even though it seems very simple! I am dealing with class Order in a simple point of sale rails app. The request is being made as the order will be deleted on page refresh (but I am getting no refresh of #orders) as I thought I am specifying in destroy.js.erb.
orders/index.html
<div id="orders">
<%= render 'orders/index' %>
</div>
<%= link_to 'New Order', new_order_path, remote: true %>
<div id="order-form" style="display:none;"></div>
orders/_index.html
<% if #orders.any? %>
<% #orders.each do |order| %>
<%= link_to "Show #{order.id}", order_path(order), class: "something" %>
<%= link_to "Delete #{order.id}", order_path(order), method: :delete, class: "something" %>
<%= link_to "Delete order with ajax", order_path(order), remote: true, method: :delete %>
<% end %>
<% else %>
<p>No orders yet</p>
<% end %>
destroy.js.erb
//When deleting order on order index - render orders again.
$('#orders').html("<%= j (render 'orders/index') %>");
and the relevant actions from orders_controller.rb
class OrdersController < ApplicationController
respond_to :html, :js
def index
#orders = Order.paginate(page: params[:page])
if params[:search]
#orders = Order.search(params[:search]).order("created_at DESC")
else
#orders = Order.all.order('created_at DESC')
end
end
def destroy
#order = Order.find(params[:id])
if #order.destroy
flash[:notices] = ["Order was successfully deleted"]
redirect_to orders_path
else
flash[:notices] = ["Order could not be deleted"]
render order_path(#order)
end
end
I suspect the issue is in my orders_controller destroy or index action, but I am a little unclear on a number of the ways of working with AJAX in Rails.
Link to repo - https://github.com/benhawker/point-of-sale-rails
Might be because after your destroy you're redirecting to the index path
I am getting no refresh of #orders
Your JS is likely not firing, you'll need the following:
def destroy
#order = Order.find params[:id]
respond_to do |format|
if #order.destroy
format.js
format.html { redirect_to orders_path, notice: "Order was successfully deleted" }
else
format.js
format.html { render order_path(#order), notice: "Order could not be deleted" }
end
end
end
This will fire app/views/orders/destroy.js.erb, which seems okay in your OP.
Try Updating your destroy action to
#order = Order.find(params[:id])
#order.destroy
#orders=Order.all
remove all the redirects
will work.

Including Ajax/JS to my voting system in Rails

How do i make it so that it does not refresh the page? instead it will just update the count numbers? Any help would be appreciated!
Stories controller:
def like
like = Like.create(like: params[:like], user: current_user, story: #story)
if like.valid?
flash[:success] = "Your selection was succesful"
redirect_to :back
else
flash[:danger] = "You can only like/dislike a story once"
redirect_to :back
end
end
index.html.erb:
<div class="pull-right">
<%= link_to like_story_path(story, like: true), :method => :put, :remote => true do %>
<i class="glyphicon glyphicon-thumbs-up"></i><%= story.thumbs_up_total %>
<% end %>
<%= link_to like_story_path(story, like: false), :method => :put, :remote => true do %>
<i class="glyphicon glyphicon-thumbs-down"></i><%= story.thumbs_down_total %>
<% end %>
</div>
Story.rb model:
def thumbs_up_total
self.likes.where(like: true).size
end
def thumbs_down_total
self.likes.where(like: false).size
end
The controller should respond_to the js "format", as described in Working with JavaScript in Rails.
Instead of redirect_to :back, respond with a meaningful status code, for example 201 for success (when a new resource has been created) or 400 for a bad request.
See RFC 2616, section 10 - Status Code Definitions.
Then, in your JS, handle the ajax:success event. This is also described in Working with JavaScript in Rails.
Let me show you an example:
First change your StoriesController as follow:
def like
#like = Like.create(like: params[:like], user: current_user, story: #story)
if #like.valid?
respond_to do|format|
format.js
end
else
respond_to do|format|
format.js {render status: 403, js: "alert('You can only like/dislike a story once'"}
end
end
end
And create a file called like.js.erb within your stories view directory with following content.
<% if #like.like %>
var $element = $(".glyphicon.glyphicon-thumbs-up");
<% else %>
var $element = $(".glyphicon.glyphicon-thumbs-down");
<% end %>
var oldCount = parseIn($element.text());
$element.text(oldCount + 1);
With the examples aside, you should at least Rails Guide in order to be able to use ajax effectively in rails. It's not that difficult.

jQuery .load()-function doesn't reload element (Rails)

In my Rails Project, I am trying to alter an instance variable via JS in a controller response (create.js.erb) and then reload an HTML-Element that makes use of the instance variable. But it doesn't work. Is it possible? This is just an example.
I also want to display the newly created object. But as I don't seem to understand the mechanism of exchanging information between rails and JS, I wanted to keep it simple here.
vocabs-controller.rb
def new
#user = current_user
#vocab = #user.vocabs.build
#vocabs = #user.vocabs.all
#count = #vocabs.count
.
.
end
def create
#user = current_user
#vocab = #user.vocabs.build(vocab_params)
#count = #user.vocabs.count
.
.
respond_to do |format|
format.html do
redirect_to new_user_vocab_path(#user)
flash[:success] = "Vocab created!"
end
format.js {render :layout=>false}
end
else
respond_to do |format|
format.html {render 'vocabs/new'}
format.js
end
end
new.html.erb (from here I make the call to the controllers create action)
<div class="panel-body">
<%= form_for(#vocab,
url: user_vocabs_path(#user),
method: :post, remote: true) do |f| %>
.
.
.
<%= f.submit "Add", class: "btn btn-large btn-primary" %>
<% end %>
<h4>
<%= #count %> Vocabs in your collection
</h4>
<%= link_to "(Show)", "#", id: "show_link" %>
<%= link_to "(Hide)", "#", id: "hide_link" %>
<ul class='vocabs <%= #vocabs_class %>'>
<% #vocabs.each do |vocab| %>
<%= render vocab %>
<% end %>
</ul>
<hr>
<%= link_to "Back", home_user_path(#user) %>
</div>
.
.
create.js.erb
<% #count+=1 %>
$('h4').load();
The server recognizes that I made a JS request and also renders create.js.erb with 200 OK. But the .load() function doesn't seem to reload the h4-Element with the new data.
When I was trying to .load() the div-element that contains the formular fields, these also weren't updated. The text input was still visible.
Further question: Where can I debug the code in JS Controller responses? I can't find them neither in Chrome's dev tools nor in Rails's server output.
If I follow you correctly, try
Add an id attribute to h4:
<h4 id="count-header">...</h4>
And in the .erb.js callback:
$('#count-header').text('<%= #count += 1 %> Vocabs in your collection');

Live Search with AJAX Ruby on Rails

I'm following the railscasts rails ajax tutorial and geting into some trouble. Everything went well, except the live keyup. The live search does not work, I have to click the search button to get the result.
Here is my application.js
$("#emos_search input").keyup(function() {
$.get($("#emos_search").attr("action"), $("#emos_search").serialize(), null, "script");
return false;
});
index.html.erb
<%= form_tag emoticons_path, :method => 'get', :id => "emos_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<div id="emos"><%= render 'emos' %></div>
<% end %>
emoticons_controller.rb
def index
#emoticons = Emoticon.search params[:search]
end
emoticon.rb
def self.search(search)
if search
where('name LIKE ? or emo LIKE ?', "%#{search}%", "%#{search}%")
else
scoped
end
end
I don't know what is the problem. I think I already followed the steps in tutorial. And there is nothing showed in js console.

Rails 3 javascript: How to render a partial with parameters

I'm still getting the hang of Rails. Here I'm using Rails 3 and the goal basically is to have an AJAX call triggered when I click the subscribe button the post_form partial is rendered beneath for the topic I have just subscribed to. The button then becomes an unsubscibe button and the post_form partial is removed. The toggling of the button alone works (i.e: by removing the second line in the two immediately following snippets), but the rendering of the *post_form* partial does not.
The problem is I can't seem to get the right syntax and/or passing of parameters in the two following partials. The topic object is just not passed and I get an invalid model_name for NilClass error when clicking on the subscribe or unsubscribe button. If I refresh the page manually, the partial is rendered or hidden the correct way, so it's really just the AJAX part that isn't working right.
views/subscription/create.js.erb
$("#subscription_form").html("<%= escape_javascript(render('users/unsubscribe')) %>");
$("#post_form").html("<%= escape_javascript(render('shared/post_form', :topic => #topic)) %>");
views/subscription/destroy.js.erb
$("#subscription_form").html("<%= escape_javascript(render('users/subscribe')) %>");
$("#post_form").html("<%= escape_javascript(render('shared/post_form', :topic => #topic)) %>");
views/users/_subscription_form.html.erb
<% unless current_user?(#user) %>
<div id="subscription_form">
<% if current_user.subscribed?(#topic) %>
<%= render 'users/unsubscribe', :topic => #topic %>
<% else %>
<%= render 'users/subscribe', :topic => #topic %>
<% end %>
</div>
<% end %>
controllers/subscriptions_controller.rb
class SubscriptionsController < ApplicationController
before_filter :signed_in_user
respond_to :html, :js
def create
#topic = Topic.find(params[:subscription][:topic_id])
current_user.subscribe!(#topic)
respond_with #topic
end
def destroy
#topic = Subscription.find(params[:id]).topic
current_user.unsubscribe!(#topic)
respond_with #topic
end
end
views/shared/_post_form.html.erb
<%= form_for(#post) do |f| %>
<div class="field">
<%= f.hidden_field :topic_id, :value => #topic.id %>
<%= f.text_area :content, placeholder: "Tell us about it ..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
If it is of any help, the relationships are:
post -> belongs_to -> topic and topic -> has_many -> posts
Looks like you're using the variable "#post" in the "views/_post_form.html.erb" file.
<%= form_for(#post) do |f| %>
Since you aren't setting that variable anywhere in your actions you would get a null reference error.
You would need to do something like this:
def create
#post = Post.find(the_post_id)
#topic = Topic.find(params[:subscription][:topic_id])
current_user.subscribe!(#topic)
respond_with #topic
end
Also you are passing in the "topic" variable as a local but accessing it as an instance variable. You should change the your _post_form.html.erb file to look like this:
<%= form_for(#post) do |f| %>
<div class="field">
<%= f.hidden_field :topic_id, :value => topic.id %>
<%= f.text_area :content, placeholder: "Tell us about it ..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
I don't have my ruby environment readily available so I can't verify that this will solve your problem but I think it should move you in the right direction.

Categories