submit two ajax forms on single page using rails - javascript

I have to separate forms on my page that are similar in that I create a comment via ajax with each.
Not functioning quite right as they are both using the same create.js.erb file.
How would I separate them so that they only render the appropriate jQuery code?
Index:
Form #1
<% form_for(#snapshot_comment, :html => { :class => "snapshot_comment", :id => "snapshot_comment" } do |f| %>
Some stuff
<% end %>
<ol id="snapshot_comments_collection">
Append stuff here...
</ol>
Form #2
<% form_for(#photo_comment, :html => { :class => "section-photo-comments", :id => "section-photo-comments" } do |f| %>
Some stuff
<% end %>
<ol id="comments-collection">
Append stuff here...
</ol>
Controller:
# POST /comments
# POST /comments.json
def create
#comment = current_user.comments.build(params[:comment])
#comment.commentable.authorize(params[:auth_key])
unauthorized! unless can? :create, #comment
if #comment.save
respond_to do |format|
format.html { redirect_to(request.headers["Referer"]) }
format.js
format.json {
render :json => #comment, :status => :created, :location => #comment
}
end
else
redirect_to(request.headers["Referer"])
end
end
Create.js.erb:
$j("<%= escape_javascript(render(:partial => #comment)) %>").prependTo("#snapshot_comments_collection");
$j('#snapshot_comment')[0].reset();
$j("<%= escape_javascript(render(:partial => #comment)) %>").prependTo("#comments-collection");
$j('#section-photo-comments')[0].reset();

You should be able to just use $() but I fail to see any use of :remote => true for your forms? Do paste the log of your rails (dev) server.

Related

Rendering Error for Ajax Upvoting System

I am using the gem "acts_as_votable" in my Rails application so that Users can vote on Posts.
I'm adding Ajax functionality so that the entire page doesn't have to refresh when a user upvotes a post. This is what I have:
routes.rb
Rails.application.routes.draw do
devise_for :users, controllers: {registrations: 'registrations'}
resources :posts do
member do
put "like", to: "posts#upvote"
put "dislike", to: "posts#downvote"
end
end
# Define Root URL
root 'pages#index'
# Define Routes for Pages
get '/home' => 'pages#home'
get '/explore' => 'pages#explore'
get '/privacy' => 'pages#privacy'
get '/:id' => 'pages#profile'
end
pages_controller.rb
def explore
#posts = Post.where('created_at >= :one_days_ago', one_days_ago: Time.now - 16.hours)
end
posts_controller.rb
class PostsController < ApplicationController
def index
#posts = Post.allow
end
def new
#post = Post.new
end
def create
#post = Post.new(post_params)
#post.user_id = current_user.id
respond_to do |f|
if (#post.save)
f.html { redirect_to :back, :flash => { :notice => "Posted" } }
else
f.html { redirect_to :back, :flash => { :alert => "Error" } }
end
end
end
def destroy
#post = Post.find(params[:id])
if current_user == #post.user
#post.destroy
end
redirect_to :back, alert: 'Deleted.'
end
def upvote
#posts = Post.find(params[:id])
#posts.upvote_by current_user
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end
def downvote
#posts = Post.find(params[:id])
#posts.downvote_by current_user
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end
private
def post_params # allows certain data to be passed via form.
params.require(:post).permit(:user_id, :content)
end
end
explore.html.erb
<% if #posts.each do |p| %>
<div class="panel-body">
<p class="post-content"><%= auto_link(p.content, :html => { :target => '_blank' }) %></p>
<%= render :partial => 'vote', :class => "vote", :locals => { p: #posts } %>
</div>
<% end %>
_vote.html.erb
<div id="vote_<%= p.id %>" class="vote">
<%= link_to 'Vote Up', like_post_path(p), :class => "upvote", :method => :put, :remote => true %>
<span><%= p.score %></span> <!--show the current vote-->
<%= link_to 'Vote Down', dislike_post_path(p), :class => "downvote", :method => :put, :remote => true %>
</div>
upvote.js.erb
$(document).ready(function(){
$('#vote_<%= p.id %>').html("<%= escape_javascript render :partial => '/pages/vote' %>");
});
When I go to run the project I get this error:
NoMethodError in Pages#explore
Showing /home/ubuntu/workspace/app/views/pages/_vote.html.erb where line #1 raised:
undefined method `id' for #<Post::ActiveRecord_Relation:0x007f6715d018e8>
Did you mean? ids
<div id="vote_<%= p.id %>" class="vote">
The issue arises from trying to render _votes.html.erb.
Where am I going wrong here? I've been stuck on this for a while and would appreciate any help. Thanks!
You are passing entire collection to partial
<% if #posts.each do |p| %>
<div class="panel-body">
<p class="post-content"><%= auto_link(p.content, :html => { :target => '_blank' }) %></p>
<%= render :partial => 'vote', :class => "vote", :locals => { p: #posts } %>
</div>
<% end %>
In line <%= render :partial => 'vote', :class => "vote", :locals => { p: #posts } %> replace #posts with p

ActionController::UnknownFormat with respond_to js in Action:Create

my route.rb
post 'home/create'
get 'home/create'
my HomeController
def create
#review_n = Review.create(review_params)
if #review_n.errors.empty?
respond_to do |format|
format.js { render 'create', locals: {review_name: #review_n.review_n, review_body: #review_n.review_body} }
end
else
render 'index'
end
end
my create.js.erb
$(function() {
$(".wrap-body").append("<div> tmp </div>");
});
rails say: ActionController::UnknownFormat in HomeController#create
I want send data in my html.erb without reload page. Help me, please!
UPD:
my html.rb
<%= form_tag home_create_path, :method => 'post', :remote => true do %>
<%= text_area_tag 'review[review_body]', nil %>
<%= text_field_tag 'review[review_name]', nil %>
<%= submit_tag 'send' %>
<% end %>
Is your code hitting the render 'index' call that is outside of the respond_to block?
Normally you would put all render calls inside the respond_to block, so it's obvious that all paths of your logic can respond to all expected formats:
def create
#review_n = Review.create(review_params)
respond_to do |format|
if #review_n.errors.empty?
format.js { render 'create', locals: {review_name: #review_n.review_n, review_body: #review_n.review_body} }
else
format.js { render 'index' }
end
end
end
This requires having both a create.js.erb and an index.js.erb (for the error case).
Also, as #sahil recommended, your routes.rb should not declare get 'home/create' - this action modifies data, so it isn't safe to make it accessible via GET.

Rails: What is wrong with this logic of trying to render a parial on click?

I'm trying to get the activities when the user clicks on a button called display
Controller:
def display
#activities = Activity.all
#activities = Activity.order("created_at desc")
#we will need to find the Post id Through Users relation to the Comments
#And this is because Activity Track, tracks Users actions, it breaks down from there.
#posts = Post.all
#user_comments = UserComment.all
respond_to do |format|
format.js { #activities = Activity.order("created_at desc") }
end
View:
<%= link_to "Display", activities_path, :remote => true %>
<div id="notify" class="section-link">
</div>
display.js.erb
$('#notify').append("<%= escape_javascript(render :partial => 'layouts/activity') %>");
_activity.html.erb
<% #activities.each do |activity| %>
<%= ActivityPresenter.new(activity, self).render_activity %>
<% end %>
Try this in display.js.erb:
$('#notify').append('<%= escape_javascript(render :partial => 'layouts/activity', :collection => #activities) %>');
Then, try this in _activity.html.erb:
<%= ActivityPresenter.new(activity, self).render_activity %>
To ensure that whenever the user clicks on "Display' the display action is invoked, you will need to adjust your routes.rb file, which is located in the config directory. You could do something like this in routes.rb:
get '/activities/display', 'activities#display', as: :activity_display
Once you make that change in routes.rb, you can edit your link_to like this:
<%= link_to "Display", activity_display_path, :remote => true %>

Unable to render more than one line using Rails and Prototype

I'm having a really odd problem (which usually means I'm doing something wrong) with rails 3.0.5 and prototype. I'm using link_to to update a div:
*views/results/index.html.erb
<%= link_to "#{school[:name]}", {:controller => "results", :action => "update", :school => school}, :remote => true%>
This calls the controller function update:
*controllers/results_controller.rb
def update
#selection = params[:school]
respond_to do |format|
format.html {redirect_to :action => 'index'}
format.js
end
end
Which renders update.js.erb ('selected' is a div in index.html.erb):
*views/results/update.js.erb
$("selected").update("<%= render :partial => '/results/academics', :locals => { :selection => #selection } %>")
Here's where it gets strange. If my partial academics.html.erb includes just one line of plain text, it works just fine. For example:
*views/results/academics.html.erb
<%= selection[:chances] %>
works fine. but if i have more than one line, it doesn't. For example:
*views/results/academics.html.erb
<%= selection[:chances] %>
<br>
Renders nothing. Server still responds with 200 OK, but div doesn't change.
What am I doing wrong?
escape_javascript is what you need
$("selected").update("<%= escape_javascript(render :partial => '/results/academics', :locals => { :selection => #selection }) %>")

Rails jQuery pageless problem

Here's the deal,
I'm trying to solve why pageless (infinite scroll) isn't rendering. Using this jQuery Plugin
I have my index page of products with pagination by will_paginate:
def index
#products = Product.find(:all, :order => "position DESC").paginate(:per_page => 3, :page => params[:page])
if request.xhr?
render :partial => 'shared/products', :object => #products
end
end
My index page is calling the products partial
<%= render "shared/products", :object => #products %>
Which in turn is passing the collection onto a singular product partial
<%= render 'shared/product', :collection => #products %>
And calling pageless on it if javascript is enabled (otherwise will_paginate steps in.
<%= pageless(#products.total_pages, products_path) %>
-----------
def pageless(total_pages, url=nil, container=nil)
opts = {
:totalPages => total_pages,
:url => url,
:loaderMsg => 'Loading more results'
}
container && opts[:container] ||= container
javascript_tag("$('#results').pageless(#{opts.to_json});")
end
And finally here is the code for the singular product partial
<% #products.each do |product| %>
<li id="product_<%= product.id %>">
<%= link_to product_image(product), product %>
</li>
<% end %>
Now when I load the page, there are no js errors, I can see the pages getting loaded in my server logs and yet nothing is rendering. Everything seems to work perfectly and yet it doesn't render. Any help would be appreciated.
-Scott
The products weren't being appended to the html. Turned out to be a class/id issue in the html. For anyone trying to debug something similar, see Jonathan Tran's comment on the question.
i changed few things to make it work for rails3:
index.html.erb
<%= render :partial => 'blah/fooPartial' , :locals => { :foo => #foo} %>
<%= will_paginate(#foo) %>
<%= pageless(#foo.total_pages, #path ) %>
My FooController:
def index
#foo = Foo.paginate(:page => params[:page], :per_page => 10).
order("created_at DESC")
respond_to do |format|
format.js
format.html # index.html.erb
end
end
My index.js.erb
$('.row').last().after("<%= escape_javascript( render :partial => 'blah/fooPartial' , :locals => { :foo => #foo}).html_safe %>");
Also Changed the ajax datatype at the very end from 'html' to 'script' in jquery.pageless.js as suggested by ahuang
Hope this helps!!!cheers!!!

Categories

Resources