J.D. J.D. - 21 days ago 5
HTML Question

Rails 5, Ajax, jQuery - Cant send received data to particular element

So, I have partial where is a table row and different table datas. By clicking a button (which is in

<tr>
) I send Ajax request (simply, with
remote: true
) and also update item data (displayed in
<tr>
) with action.

It all goes fine, but I can't send received data from Ajax to specific
<td>
. If more items being displayed - all of them receives that data.

_partial.html.erb:

<body>
<div>
<tr data-line-item-id='<%= line_item.id %>' class='line-item'>
<td data-th="Product">
<div class="row">
<div class="col-sm-2 hidden-xs"></div>
<div class="col-sm-10">
</div>
</div>
</td>
<td data-th="Price"><%= number_to_currency(line_item.product.price) %></td>
<td data-th="Quantity">
<%= line_item.quantity %>
</td>
<td data-th="Subtotal" class="text-center" class="subtotal">
<%= number_to_currency(line_item.total_price, :unit => "€", separator: ",", format: "%n %u") %></td>
<td class="actions" data-th="">
<td><%= link_to "-", decrease_line_item_path(product_id: line_item.product), remote: true %></td>
<td><%= link_to "+", increase_line_item_path(product_id: line_item.product), remote: true %></td>
</td>
</tr>
</div>
</body>


decrease.js.erb:

$("td[data-th='Quantity']").html('<%= @line_item.quantity %>');


My 'nice tries' were something like:

$(this).parent().parent().find("td[data-th='Quantity']").html('<%= @line_item.quantity %>');


But my 'best achievement' was to update only the particular, found by number item, like this:

$("td[data-th='Quantity']").eq(0).html('<%= @line_item.quantity %>');


Otherwise they all get updated...

UPDATE

This, kinda made it working, but if I increase numbers of one item and then increase other item numbers, first click shows the number of previously updated item number... But answer is close. Hope someone could help... Many thanks

increase.js.erb:

$(document).ready(function(){
$('.increase').click(function(){
var element = $(this).parent().parent()
$(element).find("td[data-th='Quantity']").html('<%= @line_item.quantity %>');
});
});

Answer

You should not add click event in js.erb file in your case as when the page loads increase.js.erb's click function is not available.

Lets say current quantity is 2.

Now on first click AJAX request is sent, in response $('.increase') function is loaded but it will not execute as the first click happened before the AJAX response.

def increase # quantity is increased to 3. end

The increase function which just loaded will have new incremented number.

// first click function loaded not triggered.
$(document).ready(function(){
  $('.increase').click(function(){
    var element = $(this).parent().parent()
    // $(element).find("td[data-th='Quantity']").html('<%= @line_item.quantity %>');
    $(element).find("td[data-th='Quantity']").html('3');
   // but as the click is not triggered in first click, the value has changed to 3.
  });
});

On second click on increase button, the first click function gets executed, changing the value of the td cell to 3. And in response to AJAX call of 2nd click on increase button, one more $('.increase').click() is loaded with a value 4. But again this newly loaded function doesn't execute.

// second click function loaded not triggered in response to second click.
$(document).ready(function(){
  $('.increase').click(function(){
    var element = $(this).parent().parent()
    // $(element).find("td[data-th='Quantity']").html('<%= @line_item.quantity %>');
    $(element).find("td[data-th='Quantity']").html('4');
   // but as the click is not triggered in second click, the value has changed to 4.
  });
});
// this 2nd function will get executed on third click.

decrease.js.erb

$('tr[data-line-item-id]').each(function(){
  if ($(this).data('line-item-id') == '<%= @line_item.id %>' ){
    $(this).each(function(){
      if ( $(this).data('th') == 'Quantity' ) {
        $(this).html('<%= @line_item.quantity %>');
      }
    });
  }
});

This can be made a lot simpler if you add an id attribute to each tr, for example:

<tr data-line-item-id='<%= line_item.id %>' id='row-<%= line_item.id %>' class='line-item'>
   ---
</tr>

and then access it in decrease.js.erb like this:

$('#row-<%= @line_item.id %> td:nth-child(3)').html('<%= @line_item.quantity %>');