AJAX not working when using <a> element

Hi everyone,

I need to use AJAX to update the database when it is clicked on an <a> element, but is not working…If I delete the href content then it works.

HTML code for that issue:

echo "<a rel='nofollow' onclick='leido(" . $id_mencion . ")' href='foro.php?foro=" . $mencion['foro'] . "&subforo=" . $mencion['subforo'] . "&hilo=" . str_replace(" ", "%",$informacion_hilo[0]['asunto']) . "&ID=" . $id_hilo . "&pagina=" . $mencion['pagina_hilo'] . "'><strong>" . $informacion_hilo[0]['asunto'] . "</strong></a>";

JS code:

<script>
function leido(foro) {
     var foro = foro;
     console.log(foro);

        $.ajax ({
          type: 'POST',
          url: 'process_leido.php',
          data: { "id_respuesta":id_respuesta }
        });

   };
</script>

And finally the code is inside the process_leido.php file:

<?php

session_start();

require 'admin/config.php';

try {
    $conexion = new PDO($bd_config['dbname'], $bd_config['usuario'], $bd_config['password'] );
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

$id = isset($_POST['id_respuesta'])? $_POST['id_respuesta'] : 0;

$statement = $conexion->prepare("UPDATE menciones SET leido = 1 WHERE id = :id");
$statement->execute(array(":id" => $id));


?>

I don’t know how to solve this problem. The href content is ok, so I don’t know if I am missing something.

<a href="..."> leads you to another page–that is what it’s supposed to do. if you want to do AJAX, don’t use a link, but any other inline element. the styling can be done in CSS, no need to mis-use <a> for that.

So the problem is that if I redirect with an <a> element AJAX is not executing? I have tried also with this:

echo "<p rel='nofollow' onclick='leido(" . $id_mencion . "," . $foro . ")'><strong>" . $informacion_hilo[0]['asunto'] . "</strong></p>";
<script>
function leido(id, foro) {
    var id_respuesta = id;
     var foro = foro;
     console.log(foro);

        $.ajax ({
          type: 'POST',
          url: 'process_leido.php',
          data: { "id_respuesta":id_respuesta }
        });

   };
</script>

But I have an error in the console saying:

missing ) after argument list

My idea is to redirect in the 'process_leido.php`, but to do that I have to pass all the parameters for the URL.

What is the content of $id_mencion and $foro - the missing ) error might be down to the content of either of those variables. What line of code does the console message say the error is on?

AJAX means asynchronously sending a request to the server and process the response on client side when it arrives. So the purpose is to actually avoid leaving the page – you can’t have it both ways. If you want to use an <a> tag for your CTA (which might be useful as a no-JS fallback), you’ll have to call event.preventDefault() in the click handler to stay on the current page.

$Id_mencion is just a number, in this case 16, and $foro also for this example is Xbox One. The error is in the first line…

 <!DOCTYPE html>

I didn’t know that, I am trying to pass all the parameters using onclick, but I am having problems.

OK, that doesn’t make sense so it probably just means that there’s an imbalance in the number of open and close brackets, and the parser can’t figure out where it is. Without seeing all the code it’s hard to offer any suggestion on that.

Yes, using onclick should be avoided. You might store those values as data-* attributes, which would be much cleaner than hard-coding JS function call in the PHP. Like e.g.

PHP

echo sprintf(
  '<a rel="nofollow" data-id="%s" data-foro="%s" class="leido" href="#"><strong>%s</strong></a>', 
  $id_mencion, 
  $foro, 
  $mencion['foro']
);

(You could also set the href attribute to some fallback page here.)

JS

document.querySelector('.leido').addEventListener('click', function leido (event) {
  var id = this.dataset.id
  var foro = this.dataset.foro

  // Prevent the default link behaviour, i.e. the redirect
  event.preventDefault()

  $.ajax ({
    type: 'POST',
    url: 'process_leido.php',
    data: { "id_respuesta": id }
  })
})

If there are more than one of those links, you can get all of them using .querySelectorAll() and iterate over them to bind that listener to each, or you might use event delegation:

document.addEventListener('click', function (event) {
  var target = event.target

  if (!target.matches('.leido')) {
    return
  }

  var id = target.dataset.id
  var foro = target.dataset.foro

  // etc.
})

BTW, you might also want to add success and error callbacks to the $.ajax() call to see if everything worked fine on the server side (and give a feedback to the user).

Thanks for the code, I keep having problems but i think that could be the way. I have tried redirecting in the file process_leido.php using header ("Location: index.php"); but it doesn’t work. How can I pass to the script more variables? using also data-* ?

I have been working on the code to adapt to my case:

                                        echo sprintf(
                                            '<a rel="nofollow" data-idmencion="%s" data-id="%s" data-foro="%s" data-subforo="%s" data-asunto="%s" data-pagina="%s" class="leido" href="#"><strong>%s</strong></a>',
                                            $id_mencion,
                                            $id_hilo,
                                            str_replace(" ", "%",$mencion['foro']),
                                            $mencion['subforo'],
                                            str_replace(" ", "%",$informacion_hilo[0]['asunto']),
                                            $mencion['pagina_hilo'],
                                            $informacion_hilo[0]['asunto']
                                        );
<script>
document.querySelector('.leido').addEventListener('click', function leido (event) {
  var id = this.dataset.id
  var foro = this.dataset.foro
  var subforo = this.dataset.subforo
  var asunto = this.dataset.asunto
  var pagina = this.dataset.pagina
  var idmencion = this.dataset.idmencion
  console.log(id)
  console.log(foro)
  console.log(subforo)
  console.log(asunto)
  console.log(pagina)
  console.log(idmencion)

  // Prevent the default link behaviour, i.e. the redirect
  event.preventDefault()

  $.ajax ({
    type: 'POST',
    url: 'process_leido.php',
    data: { "idmencion": idmencion }
  })


  // IF I USE THIS REDIRECTION, I GOES TO THE URL, BUT THE DATABASE IS NOT UPDATED
  window.location.replace("foro.php?foro=" + foro + "&subforo=" + subforo + "&hilo=" + asunto + "&ID=" + id + "&pagina=" + pagina);
})
</script>

In the process_leido.php file:

<?php

session_start();

require 'admin/config.php';

try {
    $conexion = new PDO($bd_config['dbname'], $bd_config['usuario'], $bd_config['password'] );
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}

$id = isset($_POST['idmencion'])? $_POST['idmencion'] : 0;

$statement = $conexion->prepare("UPDATE menciones SET leido = 1 WHERE id = :id");
$statement->execute(array(":id" => $id));

//this redirection is not working...
header("Location: foro.php");

?>

So…I have trying to redirect to the URL in the script, and yes, I redirects, but it doesn’t update the database. If I delete the redirection from javascript and redirect in the process_leido.php, then the header("Location: foro.php") doesn’t redirect.

I don’t know what I have to do, i am lost.

You’ll have to place the redirect in the success callback, so that it happens after the response arrived. Setting the location in the PHP script will have no effect (on the client side) as you’re currently discarding the response anyway.

That said, if you’re doing a redirect anyway, why don’t you simply use a regular link and encode the variables in the query string? Then you can perform a redirect with PHP using header(), which is much better than doing so within the browser.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.