Reputation: 10797
I'm trying to do an ajax "button" (not an actual form button) that behaves just like a normal link_to "content", some_path, remote:true
would. And when I click it, it swaps out the image to indicate the status (e.g. on/off, voted/not voted, etc.)
The reason is, I want to use javascript to add class, to swap out images, toggling them. Usually, people do this by specifying the background-image property in CSS for a given class, and add/remove classes via javascript.
But of course, if you use the rails link_to, that creates an a tag, which is an inline element. This inline element is not friendly for the desired above mentioned behavior. You end up having to use an actual image tag, making the javascript DOM traversal, as well as the CSS messier. You also end up doing silly stuff like
<div>
<a>
<div>
</div>
</a>
</div>
just to keep the link tag as an a
tag, while trying to ensure a certain size of the "button"
I am looking for an elegant way to accomplish creating a simple ajax "button" that behaves just like a remote link, where it's not a form button, and where I can simply add/remove a class to the element in order to swap out images via CSS.
Is there a good solution to this? Or will I have to use spaghetti jquery and ajax calls on a div element with a specified size? (I've tried nesting a content_tag
within a link_to
but that's no better than nesting an image_tag
in place of the content_tag
) (I've thought about doing display: block
to the a tag with width: 100%
. Is this method any good? why?)
Upvotes: 0
Views: 289
Reputation: 3080
The remote option on link_to was created to allow ajax requests to the link URL. As you are querying the server, the change of class should only occur when the AJAX query is successfully completed. I would do it that way:
<%= link_to "Vote", some_path, remote:true, "data-type" => :json, class: "vote-button" %>
With the following jquery code:
$('.vote-button').on('ajax:success', function(evt, data, status, xhr){
if(data.voted == true){
$(this).addClass("voted");
}else{
$(this).removeClass("voted");
}
})
Assuming your controller action returns a JSON object containing the voted key:
class VoteController < ApplicationController
def update
voted = # Some stuff happening here that says if voted or not
render :json => {voted: voted}
end
end
And your css would look like:
.vote-button{
background-image: asset-url(unvoted.png);
}
.vote-button.voted{
background-image: asset-url(voted.png);
}
Don't just copy paste this as I'm not 100% sure it works, but you get the idea.
Upvotes: 1