Hi I am currently making an app with users, albums, and photos. I managed to make the AJAX work for the create action when I upload pics, but I can't get AJAX to work for the delete. Instead, it redirects me to an empty show page for the pic. Can anyone give me some guidance?
photos controller:
def destroy
#user = User.find(params[:user_id])
#album = #user.albums.find(params[:album_id])
#photo = #album.photos.find(params[:id])
# #photo.destroy
flash[:success] = "Photo successfully deleted."
respond_to do |format|
if #photo.destroy
format.js
# format.json { render json: #photo, status: :created, location: #photo}
# redirect_to user_album_path(#user, #album)
end
end
end
destroy.js.erb (I'm supposed to have this right?)
$('.destroypicswrapper').remove(".<%= #photo.avatar.url %>");
_photodestroy.html.erb partial:
<div class="picthumb <%= photo.avatar.url %>">
<%= link_to image_tag(photo.avatar.url ? photo.avatar.url(:small) : #album.name), root_url %>
<br>
<%= link_to "Delete", user_album_photo_path(#user, #album, photo), :remote => true, method: :delete, data: { confirm: "Are you sure? "} %>
</div>
and finally the albums/edit.html.erb page where the delete is initially happening:
<% provide(:title, "Edit album") %>
<%= render 'form' %>
<div class="destroypicswrapper">
<% if #album.photos.any? %>
<%= render :partial => 'photodestroy', :collection => #album.photos, :as => :photo %>
<% end %>
</div>
I don't think you want to render the full url of an image as a class of a div. Also, your Jquery is wrong. Try something like this:
destroy.js.erb
$('.destroypicswrapper > #photo_<%= #photo.id %>').remove();
Adjust your _photodestroy.html.erb to:
<div class="picthumb" id="photo_<%= photo.id %>">
Related
I have a button that adds a vote to a post whenever a user clicks it. The posts are being rendered in the index view, but when the button is clicked for a user to add a vote, I get a 500 error in the console, but on refresh the vote has been added. Below is the code I'm using:
Pages Controller where the posts are being rendered:
#posts = current_user.feed.paginate(:per_page => 6, page: params[:page])
Favorites Controller:
def create
current_user.favorites.create(:post_id => params[:post_id])
respond_to do |format|
format.html { redirect_to post }
format.js { render :toggle }
end
end
Toggle.js.erb (favorites/toggle.js.erb)
$("#favorite").html("<%= escape_javascript render('shared/fave_form') %>");
Favorite Form
<% if current_user.favorites.find_by_post_id(post.id) %>
<% else %>
<%= form_for favorite, :html => { :method => :delete }, :remote => true do |f| %>
<%= f.submit "Unlike" %>
<% end %>
<% end %>
I am able to update the like and unlike button via ajax, but I am not able to update the like count.
Post has_many likes
likes_controller.rb
def create
#like = Like.new(:post_id => params[:post_to_be_liked])
if #like.save
respond_to do |format|
format.html {redirect_to :back, notice: "Liked!"}
format.js
end
end
end
view.html.erb
<% #post = user.posts.first %>
<div id="send_like_for_<%= #post.id %>">
<% if #post.is_liked?(#post, current_user)%>
<%= render 'unlike'%>
<%else%>
<%= render 'like'%>
<%end%>
</div>
<div id="liked_<%= #post.id %>" %>
<%= render 'liked_users'%>
</div>
create.js.erb
$("#send_like_for_<%= params[:post_to_be_liked]%>").html("<%= escape_javascript(render('users/unlike')) %>")
$("#liked_<%= params[:post_to_be_liked]%>").html("<%= escape_javascript(render('users/liked_users')) %>")
_like.html.erb
<%= link_to "LIKE", likes_path(:post_to_be_liked => #post.id), remote: true, :method=>:post %>
_unlike.html.erb
<span> UNLIKE </span>
_liked_users.html.erb
<%= "#{#post.likes.length} like this" %>
The like/unlike functionality works just fine and when someone likes the post the button changes to Unlike. But the like count doesn't increase.
But why are you doing this in your view?
<% #post = user.posts.first %>
It will update only your first post always. I can't understand.
Try with this:
_liked_users.html.erb
<%= #updated_post = Post.where(id: #post.id) %>
<%= "#{#updated_post.likes.length} like this" %>
or
<%= #post.reload %>
<%= "#{#post.likes.length} like this" %>
Edit (Try to build your like this):
def create
#post = Post.where(id: params[:post_to_be_liked])
#like = #post.likes.build(:post_id => #post.id)
if #like.save
respond_to do |format|
format.html {redirect_to :back, notice: "Liked!"}
format.js
end
end
end
I think you should try to do this
#post = user.posts.first
after save in your controller and remove <% #post = user.posts.first %> from erb file and if it is not possible then initialize #post in your controller#create
#post = Post.find(params[:post_to_be_liked])
When I add a model in my index action, the create action is invoked that adds an instance of the model to the database. This is the following create action:
tracks_controller.rb
def create
#track = Track.new(params[:track])
if #track.save
redirect_to(root_url) //Want to change this!
else
#tracks = Track.all
render :action=>"index"
end
end
Where you can see that I am redirected to my root url (where I want to be) everytime create is invoked. However, how can I carry this out without refreshing the page? Since tracks are being played, I do not want the page to be refreshed whenever something is added to the database.
If I change this line to render :action=>"index", then I receive the following error in my index.html.erb file
undefined methodeach' for nil:NilClass`
15: <p>Database is empty!</p>
16: <%else%>
17: <br>
18: <% #tracks.each do |track| %>
19: <div id="list_container">
20: <ul>
21: <li class="list_container">
How do I go about achieving this?
form
<%= form_for #track, remote: true %>
form fields
<%= f.submit %>
<% end %>
app/views/tracks/create.js.erb
<% if #track.valid? %>
$(".tracks").prepend('<%= j(render(#track)) %>'); // make sure you have _track.html.erb
$("ID OR CLASS OF YOUR FORM")[0].reset(); // this will clear your form inputs
<% else %>
alert('Something Went Wrong');
<% end %>
app/views/tracks/index.html.erb
<div class="tracks">
<% #tracks.each do |track| %>
<%= render :partial => 'track' %>
<% end %>
</div>
app/views/tracks/_track.html.erb
some code here to show track:
<div>track.id</div>
<div>track.name</div>
index.html.erb needs the #tracks variable. Therefore, you have to set it before rendering the page.
For example:
def create
#track = Track.create(params[:track])
#tracks = Track.all
render :action => "index"
end
The simplest, quickest way to get it is to add :remote => true to you form_for!
If you are posting track from a form then make the remote to true
like
<%=form_for #track, :remote => true do |f| %>
your input fields
<%end %>
index.html.erb
<div id="track_list">
<%= render :partial => 'tracks_record' %>
</div>
_tracks_record.html.erb
<% #tracks.each do |track|%>
your code
<% end %>
in controller
def create
#track = Track.create(params[:track])
#tracks = Track.all
respond_to do |format|
format.js
end
end
Create one js.erb file for create.js.erb
<% if #track.valid? %>
('#track_list').html('<%= escape_javascript( render :partial => "tracks_record" ) %>');
<% else %>
alert('Could not save');
<% end %>
This will refresh the data and populate the new entries without refreshing the page.
Unfortunately I can't comment on Debadatt's suggestion but I found it much better than the top post. My only notes are to change this to
def create
#track = Track.create(params[:track])
#tracks = Track.all
respond_to do |format|
format.js
end
end
to this:
def create
#track = Track.create(params[:track])
#tracks = Track.all
respond_to do |format|
format.js { render layout: false, content_type: 'text/javascript' }
end
end
And this:
('#track_list').html('<%= escape_javascript( render :partial => "tracks_record" ) %>');
to this:
$('#track_list').html('<%= escape_javascript( render :partial => "tracks_record" ) %>');
Great suggestion thanks Debadatt
I have a page called /add that you can add a Dog on and the form is in its own partial. I'm using Simple Form and Twitter Bootstrap. I added the files for the main Bootstrap but use a gem for simple_form to work with it just so you know.
DogsController
# new.js.erb (deleted new.html.erb)
def new
#dog = Dog.new
respond_to do |format|
format.js
end
end
# create.js.erb
def create
#dog = current_user.dogs.new(params[:dog])
respond_to do |format|
if #dog.save
format.html { redirect_to add_url, notice: 'Dog was successfully added.' }
format.json { render json: #dog, status: :created, location: #dog}
format.js
else
format.html { render 'pages/add' }
format.json { render json: #dog.errors, status: :unprocessable_entity }
end
end
end
dogs/_form.html.erb
<%= simple_form_for(#dog, :remote => true) do |f| %>
<%= render :partial => "shared/error_message", :locals => { :f => f } %>
<%= f.input :name %>
<%= f.button :submit, 'Done' %>
<% end %>
This line: <%= render :partial => "shared/error_message", :locals => { :f => f } %>
Is for bootstrap so it renders the errors html correctly.
PagesController
def add
respond_to do |format|
format.html
end
end
pages/add.html.erb
<div id="generate-form">
</div>
dogs/new.js.erb
$("#generate-form").html("<%= escape_javascript(render(:partial => 'dogs/form', locals: { dog: #dog })) %>");
Now how would I get this to render the error partial as if it was still on my dogs/new.html.erb since its being created through AJAX? I don't need client side validations do I?
EDIT
shared/_error_message.html.erb
<% if f.error_notification %>
<div class="alert alert-error fade in">
<a class="close" data-dismiss="alert" href="#">×</a>
<%= f.error_notification %>
</div>
<% end %>
Through our chat you mentioned you also had a create.js.erb and that file was clearing out the form.
making the the create.js the same as new.js.erb :
$("#generate-form").html("<%= escape_javascript(render(:partial => 'dogs/form', locals: { dog: #dog })) %>");
made it work.
You don't have to do client side validations. But should,it is common to disable the submit button via js until client side validation is met.
also I would not delete the new.html.erb incase a client doesn't.have js turned on.
I think your add may need format.js to your add and
remote = true to your shared errors partial call
I have method in my controller:
def work_here
#company = Company.find(params[:id])
current_user.work_apply(current_user, #company)
redirect_to company_path
end
On my view:
<%= render 'companies/work_form' if signed_in? %>
_work_form.html.erb:
<%= form_for company, :remote => true, :url => { :controller => "companies", :action => "work_here" } do |f| %>
<%= f.hidden_field :id, :value => company.id %>
<%= f.submit "I working here" %>
<% end %>
And I have a work_here.js.erb file:
$("#work_at_form").html("<%= escape_javascript("render('companies/works')") %>")
But my form works without ajax request(in other pages ajax forks fine), my js.erb file never use.
Can anyone give me advise?
Thanks.
The work_here.js.erb can't be read because you never call it. A redirect is allways do. render it when the request is js format.
def work_here
#company = Company.find(params[:id])
current_user.work_apply(current_user, #company)
respond_to do |format|
format.html { redirect_to company_path }
format.js { render }
end
end