2

According to this answer and many others on SO i've seen ways to refresh Ajax content (after the success call) on the element if it has an ID. However, I need to get this behaviour on classes. I've tried variations of using $.each, foreach, this, etc but they all produce similar (incorrect) results. Can anyone teach me how to refresh the content for the current clicked item only?

This is how i'm doing it, but after clicking the report button, 16 more buttons appear, because it's calling all the buttons with that class.

<!--html:-->
<!-- If userReported function returns true, then user already reported this item. -->
<!-- This code block runs in a loop of about 10-17 iterations -->
            <span class="report-btn_wrapper refresh-report-after-ajax">
            <i <?php if (userReported($product_ref)) { ?> title="Report this item" class="fa fa-flag-o report-btn" <?php } else { ?> title="You reported this item" class="fa fa-flag report-btn" <?php } ?> data-id="<?=$product_ref;?>" data-uid="<?=$user_ref;?>"></i>
            </span>
//javascript:
$('body').on('click', '.report-btn', function (e) {
    var id = $(this).data('id');
    var uid = $(this).data('uid');
        $.ajax({
            type: 'POST',
            url: 'report.inc.php',
            data: {
              product_ref : id,
              user_ref : uid
            },
            success: function (html) {
                //give user a notification message
                notification(html, 0);
                //refresh the button (if user clicked, button is red, if user did not click, button is grey)
                $(".refresh-report-after-ajax").load(window.location + " .refresh-report-after-ajax"); 
            }
        });
        e.preventDefault();
    });

What is happening:

enter image description here

What I'm trying to achieve:

enter image description here

ArabianMaiden
  • 505
  • 7
  • 24
  • 1
    Add `var $this = $(this)` at the beginning of the `click function` and then in `success function` do whatever you need with `$this` (_`$this` is clicked button_) – Mehdi Dehghani Mar 10 '19 at 10:21
  • Inside the click handler, but before the AJAX call, `this` refers to the clicked button. Use something like `var $span = $(this).closest('.some-parent-class').find('.refresh-report-after-ajax');` to store it. In your success call, use `$span.load(...);` (you should also check the URL you're loading, because I don't think you mean to make the class a part of it?) –  Mar 10 '19 at 10:21
  • I've tried this logic, but it fails because the classes are still duplicating from within the load() function. Maybe there's a completely different approach when using classes because the load() function calls a class - it doesn't know which class to call so it gets all. – ArabianMaiden Mar 10 '19 at 10:26
  • @MehdiDehghani I have added the HTML - since it's in a while loop there are plenty of duplicate classes on the same page.. – ArabianMaiden Mar 10 '19 at 10:28

1 Answers1

1

If you only want to update the clicked button, just get yourself the reference to it and call the update on the surrounding element:

$('body').on('click', '.report-btn', function (e) {
    var $button = $(this);
    var id = $button.data('id');
    var uid = $button.data('uid');
    $.ajax({
        type: 'POST',
        url: 'report.inc.php',
        data: {
          product_ref : id,
          user_ref : uid
        },
        success: function (html) {
            //give user a notification message
            notification(html, 0);
            //refresh the button (if user clicked, button is red, if user did not click, button is grey)
            $button.closest(".refresh-report-after-ajax").load(window.location + " .refresh-report-after-ajax"); 
        }
    });
    e.preventDefault();
});

UPDATE

Instead of the .load(…) call, you can directly perform your changes in JavaScript, since you know, what the result should be:

$button.toggleClass('fa-flag-o fa-flag').attr('title', $button.hasClass('fa-flag') ? 'You reported this item.' : 'Report this item');
Christoph Herold
  • 1,799
  • 13
  • 18
  • This gives the same result, I had tried it before. I think because the ```window.location + " (class) "``` is getting all of the classes. How can i single out the current class only? – ArabianMaiden Mar 10 '19 at 10:24
  • 1
    But that has to be wrong logic on the part of your PHP code. To me, it looks like you are probably creating multiple buttons inside a loop. Calling back to `window.location + " .refresh-report-after-ajax"`is probably not, what you are trying to do, as Chris G already pointed out. – Christoph Herold Mar 10 '19 at 10:28
  • How could I remove the buttons from the loop tho? The page is looping through a database and styling them as they are echoed out. I'm not sure how to separate the buttons from the products – ArabianMaiden Mar 10 '19 at 10:33
  • I assume, you need an extra parameter to your url, so that the PHP script only renders the flag you want to update. Try adding your `id` and `uid` and extending your php script to filter based on the parameters, if they exist. On the other hand: Why not simply change your styling and title directly in JavaScript, without needing the extra callback? You know, what the result should be. – Christoph Herold Mar 10 '19 at 10:40
  • I'll try the extra url parameter and let you know :) Reason I didn't do the styling directly in the url - I had a reason but totally forgot. – ArabianMaiden Mar 10 '19 at 10:42
  • 1
    See my update, it does not perform a second callback. Instead, it toggles the fa-flag-o and fa-flag classes and toggles the title accordingly. – Christoph Herold Mar 10 '19 at 10:44
  • Brilliant! You're a star :) I still can't remember why I hadn't done this. Since it's a one-way button only (users not allowed to retract their input) I used: ```$button.removeClass('fa-flag-o').addClass('fa-flag').attr('title', $button.hasClass('fa-flag') ? 'You reported this item.' : 'Report this item');``` – ArabianMaiden Mar 10 '19 at 10:49