4
\$\begingroup\$

In my Rails 4 app I have this event listener:

$('.remove-tag-button').on('click', function () {
 $.ajax({
 type: "POST",
 data: {id: <%= @item.id %>, tag: $(this).data("tag-name")},
 url: "/remove_tag"
 });
 });

in three places and I'm wondering if there's a way to refactor.

I have an items controller with some actions including show, add_tag, and remove_tag.

def show
 @item= Item.find_by_id(params[:id])
end
def add_tag
 (omitted for brevity)
 respond_to do |format|
 format.js
end
def remove_tag
 (omitted for brevity)
 respond_to do |format|
 format.js
end

My show.html.erb has a form with a button to remove tags (class="remove-tag-button") that the event listener is referring to. I have the listener inside script tags at the bottom of my show.html.erb (inside a $(document).ready()) and also inside my add_tag.js.erb and remove_tag.js.erb.

show.html.erb

<div id="taglist">
 <%= render partial: 'items/tag_list', locals: {item: @item} %>
 </div>
 <form action="<%= add_tag_path %>" method="post" id="custom-tag" class="input-group" autocomplete="off" data-remote="true">
 <%= text_field_tag :tag, nil, placeholder: 'Add tag', class: "form-control typeahead", id: 'add-tag' %>
 <span class="input-group-btn">
 <%= submit_tag 'Add', id: "add-button", class: "btn btn-default" %>
 </span>
 </form>
<script>
$(document).ready(function(){
 $('.remove-tag-button').on('click', function () {
 $.ajax({
 type: "POST",
 data: {id: <%= @item.id %>, tag: $(this).data("tag-name")},
 url: "/remove_tag"
 });
 });
});
</script>

add_tag.js.erb

$("#taglist").html('<%= escape_javascript(render partial: "items/tag_list", locals: {item: @item}) %>');
$('.remove-tag-button').on('click', function () {
 $.ajax({
 type: "POST",
 data: {id: <%= @item.id %>, tag: $(this).data("tag-name")},
 url: "/remove_tag"
 });
});

remove_tag.js.erb

$("#taglist").html('<%= escape_javascript(render partial: "items/tag_list", locals: {item: @item}) %>');
$('.remove-tag-button').on('click', function () {
 $.ajax({
 type: "POST",
 data: {id: <%= @item.id %>, tag: $(this).data("tag-name")},
 url: "/remove_tag"
 });
});

items/_tag_list.html.erb

<% item.all_tags_list.each do |t| %>
 <span class="tag-container">
 <%= link_to t, tag_path(t), class: "item-tag" %>
 <% if item.tags_from(current_user).include?(t) %>
 <span>
 <%= link_to "×ばつ", '', class: "remove-tag-button", :'data-tag-name' => t, remote: true %>
 </span>
 <% end %>
 </span>
<% end %>

I have 3 instances of this code because a user needs to be able to add and remove tags through AJAX requests while on the page. So it listens when the page loads, then I need it to still be listening after a user has added and/or removed a tag (both which are done through AJAX).

This seems sloppy. I'm wondering if theres a better way to do it.

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Jan 8, 2016 at 3:50
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

I was able to get rid of the duplicate code by using event delegation. I changed my event listener to:

$('#taglist').on('click', '.remove-tag-button', function () {
 $.ajax({
 type: "POST",
 data: {id: <%= @item.id %>, tag: $(this).data("tag-name")},
 url: "/remove_tag"
 });
 });
answered Jan 9, 2016 at 0:07
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.