0

Essentially, when I create a comment using AJAX request and then append the comment div structure to my comments-container div, the X icon that is used to trigger an AJAX request that deletes the comment doesn't work and I don't get any errors.

If I create a comment and then refresh the page, I can delete it just fine so the problem is related only to comments that are programmatically created with JavaScript.

I'm not sure how to troubleshoot since I'm not getting any errors in the console or anything.

This is the AJAX used for posting a comment:

$('.post-comment').on('click', function(event) {
    event.preventDefault();
    var userId = $("input[name=user_id]").val();
    var imageId = $("input[name=image_id]").val();
    var comment = $("textarea[name=comment]").val();

    $.ajax({
        method: 'POST',
        url: urlComment,
        data: {
            userId: userId,
            imageId: imageId,
            comment: comment,
            _token: token
        }
    }).done(function(response) {
        var commentsCount = response.image.comments;
        var comment = response.comment.comment;

        var appendHtml =    '<div class="comment-flexbox">' +
                                '<div class="comment-container">' +
                                    '<a href="../profile/' + response.image.user.username + '">' +
                                        '<img class="comment-picture" src="../storage/uploads/profile_pictures/edited/'+ response.image.user.image_file_name +'">' +
                                    '</a>' +
                                '</div>' +
                                '<div class="comment-info-container">' +
                                    '<a href="../profile/'+ response.image.user.username +'">' + response.image.user.username + '</a>' +
                                    '<p>' + comment + '</p>' +
                                '</div>' +
                                '<div class="comment-actions-container">' +
                                    '<i class="fas fa-times delete-comment" data-id="' + response.comment.id + '"></i>' +
                                '</div>' +
                            '</div>';

        $("textarea[name=comment]").val("");

        if ($('.comments-container').length) {
            $('.comments-container').prepend(appendHtml);
        } else {
            var x = document.createElement("div");
            var artworkInfoContainer = $('.artwork-info-container');
            artworkInfoContainer.append(x);
            x.className = "comments-container";
            $('.comments-container').prepend(appendHtml);
        }

        $('.comments-count').html("<i class='far fa-comments fa-fw'></i>" + commentsCount + " Comments")
    })
});

And this is the AJAX used for deleting a comment:

$('.delete-comment').on('click', function(event) {
    var commentId = $(this).data('id');
    var flexbox = $(this).parents().eq(1);
    $.ajax({
        method: 'POST',
        url: urlDeleteComment,
        data: {
            commentId: commentId,
            _method: 'delete',
            _token: token
        }
    }).done(function(response) {
        flexbox.remove();
    })
});

And finally, this is the HTML structure that I'm creating with JavaScript. It is using blade template and PHP:

            <div class='comments-container'>
                @foreach($comments as $comment)
                    <div class="comment-flexbox">
                        <div class="comment-container">
                            <a href='{{ route('profile', $comment->user->username) }}'>
                                <img class='comment-picture' src='{{ url("storage/uploads/profile_pictures/edited/".$comment->user->image_file_name )}}'>
                            </a>
                        </div>
                        <div class="comment-info-container">
                            <a href='{{ route('profile', $comment->user->username) }}'>{{ $comment->user->username }}</a>
                            <p>{{ $comment->comment }}</p>
                        </div>
                        <div class="comment-actions-container">
                            @auth
                                @if(Auth::id() === $comment->user->id || Auth::user()->hasRole('Admin'))
                                    <i class="fas fa-times delete-comment" data-id="{{ $comment->id }}"></i>
                                @endif
                            @endauth
                        </div>
                    </div>
                @endforeach
            </div>
Onyx
  • 5,186
  • 8
  • 39
  • 86

1 Answers1

2

In your code for deleting a comment, you should delegate the event using the document, like so:

$(document).on('click', '.delete-comment', function(event) {

This way, any new elements appended to the document, will still 'hear' this event.

Stuart
  • 6,630
  • 2
  • 24
  • 40
  • That is quite interesting. I'd have to read up on that. Thanks – Onyx Dec 21 '18 at 20:18
  • Glad to help. Do read through https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements (the question this one is marked as a duplicate of) because it has some great links, and explanations that will help you. – Stuart Dec 22 '18 at 10:13