Angel Politis Angel Politis - 1 year ago 47
Ajax Question

The onclick event doesn't work on reloading elements

I have created a user support system to enable users to contact the moderators of my website in case they need help with their account and the opposite.

As of recently, new messages sent to or by the users get loaded only if the page is refreshed, which is not very convenient as a user may sign out without refreshing and therefore not get the message soon.

To counter that, I thought of implementing a

sending an AJAX request every 1 minute and reloading the messages from the database, so that if new ones exist they will be shown.

While it actually works and reloads the messages, when I click on a message to open it and read it the
event is not fired
. This happens for all messages without exception.

I thought that the problem was that
reloaded all the messages every minute instead of checking if new messages exist and reload them only in that case, but despite performing this check in my PHP file the problem still persists.

My PHP code for a notification:

$message_status = ($status[$a] === "Read") ? "-open" : ""; ?>

<div class="dashboard-notifs-content">
<i class="fa fa-folder<?php echo $message_status; ?> fa-fw">&nbsp;</i>
<a class = "user-notifs" notif-id = "<?php echo $ID[$a]; ?>"
subject = "<?php echo $subject[$a]; ?>" message = "<?php echo $message[$a]; ?>"
status = "<?php echo $status[$a]; ?>"><?php echo $subject[$a]; ?></a>

My code for the

// Show message in preview
$(".user-notifs").on("click", function() {
// Declare variables and assign to them the content of their respective attributes
var current = this;
var id = this.getAttribute("notif-id");
var subject = this.getAttribute("subject");
var message = this.getAttribute("message");
var status = this.getAttribute("status");

// Assign notification-id to the preview window
document.getElementById("user-notif-preview").setAttribute("notif-id", id);

// Display the preview lightbox and show the message = "block";
document.getElementById("user-subject").value = subject;
document.getElementById("user-message").value = message;

/* Check if the notification has already been opened
to mark it as read in the database */
if (status === "Unread") {
// Mark notification as opened
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState === 1) {
current.previousElementSibling.className = "fa fa-folder-open fa-fw";
};"POST", "notifs.php", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("notif_status=Read&notif_id=" + id);

My code for

var notifications = document.getElementById("dashboard-notifs");

// Update the notifications
setInterval(function() {
var yhttp = new XMLHttpRequest();
var number = $("#dashboard-notifs").children(".dashboard-notifs-content").length;
yhttp.onreadystatechange = function() {
if (yhttp.readyState === 4 && yhttp.status === 200) {
// Display the notifications if the response is not empty
if (yhttp.responseText.length !== 0) {
notifications.innerHTML = yhttp.responseText;
};"POST", "update.php", true);
yhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
yhttp.send("content=notifs&number=" + number);
}, 5000);

I have only managed to find this question on Stack Overflow, which is kind of similar, but unfortunately none of the answers there solves my issue.

Answer Source

You are directly binding the onclick event using on. You should use event delegation.

You can write the onclick event in this way.

$(document).on("click", ".user-notifs",function() {
   //script goes here

Instead of document you can also use the parent element closer to the target element.

$(class_or_id_of_closer_parent_ele).on("click", ".user-notifs", function() {
    //script goes here