-1

I am trying to trigger a JQuery Ajax event for a bunch of buttons.

Here is the code in index.php file :

<?php 
foreach($data as $d) {
  $myid = $d['id']; 
  $mystatus = $d['status']; 
  ?>

  <div class="input-group-prepend">
    <button id="submitbtn" type="button" class="myupdatebtn btn btn-success" data-id="<?php echo $myid; ?>" disabled>Finish Task</button></div>

    <li class="nav-item">
      <a class="nav-link clickable blueMenuItem" id="nav-location" data-id="<?php echo $d['id']; ?>">
        <i class="nav-icon fas <?php echo $d['icon']; ?>"></i>
        <p>
          <?php echo $d["title"];
            if ($d['type'] == "task") { ?>
              <span id="updatemsg-<? echo $d['id'];?>" class="right badge <?php if($mystatus == "TERMINATED"){echo "badge-success";} else {echo "badge-danger";}?>"><?php setTerminated($conn, $myid)?></span>
          <?php } ?>
        </p>
      </a>
  </li> 
<?php } ?>

Where the menu items (titles, status and icons) are extracted from a MySQL Database.

Here is the JAVASCRIPT (JQUERY) file with AJAX call :

$('.myupdatebtn').on('click', function() { 
    var id = $(this).data('id'); 

    $.ajax({ 
      url: 'includes/updatestatus.php', 
      type: 'POST', 
      data: {id:id}, 
      dataType: 'html', 
      success: function(data)
      { 
        if (data) 
        { 
          $('#submitComment').attr("disabled", true); 
          $('#customComment').val("");
          $('#updatemsg-'+id).html("TERMINATED").removeClass('badge-danger').addClass('badge badge-success'); 
          console.log(id);
        } 
        else 
        { 
          $('#customContent').load("custom/static/error.html"); 
         } 
       }, 
       error: function(jqXHR, textStatus, errorThrown)
       { 
         $('#customContent').html("ERROR MSG:" + errorThrown); 
       } 
    }); 
});

This is the code for the updatestatus.php file :

 <?php

    include("db.php");
    $id = $_POST['id'];
    $query = "UPDATE mytable SET status='TERMINATED' WHERE id='$id'";
    mysqli_query($conn, $query);
      
    ?>

As you can read from the code, when the button is clicked, it will be disabled and the input will be empty. The problem is that this code runs only once, after that the button will not updated the DATABASE and the DOM will not be updated (only after refresh and press the button again).

Is there a way to terminate the JQuery event after each iteration (Button pressed for every menu item) and make it available again to be executed?

ADyson
  • 57,178
  • 14
  • 51
  • 63
1heone
  • 17
  • 6
  • Refer https://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements – Devsi Odedra Nov 30 '21 at 11:09
  • 1
    **Warning:** Your code is vulnerable to SQL Injection attacks. You should use parameterised queries and prepared statements to help prevent attackers from compromising your database by using malicious input values. http://bobby-tables.com gives an explanation of the risks, as well as some examples of how to write your queries safely using PHP / mysqli. **Never** insert unsanitised data directly into your SQL. The way your code is written now, someone could easily steal, incorrectly change, or even delete your data. – ADyson Nov 30 '21 at 11:43
  • https://phpdelusions.net/mysqli also contains good examples of writing safe SQL using mysqli. See also the [mysqli documentation](https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php) and this: [How can I prevent SQL injection in PHP?](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) . Parameterising your queries will also greatly reduce the risk of accidental syntax errors as a result of un-escaped or incorrectly quoted input values. – ADyson Nov 30 '21 at 11:43
  • This code will only ever handle the click on the first Submit button. IDs in HTML (as everywhere else) must be **unique** (by definition!) but your code will generate multiple buttons with the same ID. jQuery will only bind the click to the first one because the others are considered not valid. Use a class instead so you can bind the click event to multiple elements with the same class. – ADyson Nov 30 '21 at 11:45
  • @DevsiOdedra No that's not relevant to this issue. – ADyson Nov 30 '21 at 11:45
  • `Is there a way to terminate the JQuery event after each iteration (Button pressed for every menu item)`...so you mean that the user must update all the records before the Submit buttons become active again? I won't comment too much on the UX of that (except to say...yuk!) but basically you'd need to count how many buttons are on the page, and then count how many of them are disabled. Fairly easy with CSS selectors. If they're all disabled, re-enable them all again (which is also easy if they all have the same class...) – ADyson Nov 30 '21 at 11:49
  • @ADsyon No the user should update only the selected item (press the button bound to that item). I've tried to bind the event to a CLASS instead of ID as you suggested (added a class to the button, i called it here : myupdatebtn) and then triggered the event through ```$('.myupdatebtn').on('click', function(){#code}``` but the same result. – 1heone Nov 30 '21 at 11:55
  • `No the user should update only the selected item (press the button bound to that item).`..., ok so then what did you mean by `Is there a way to terminate the JQuery event after each iteration (Button pressed for every menu item)`? It's not clear what the actual problem is. The button becomes de-activated after clicking because you've disabled it in your code. In what circumstances do you want it to be re-enabled, exactly? – ADyson Nov 30 '21 at 11:59
  • `I've tried to bind the event to a CLASS instead of ID as you suggested ...same result`...what result precisely? That was an aside about it only working for one record, it's not related to the buttons being disabled by your code. But if it still isn't doing what you expected, please update the question to show the new version of the code, then we can see _exactly_ what you've done. – ADyson Nov 30 '21 at 12:00
  • @ADyson i've edited the code and added a ```console.log(id)```when the data are returned so when i click on a Button i can see in the console which ID has been returned. The first Click event is executed as expected, after that the other buttons doesn't behave the same (DOM is not updated). of course the button will be disabled and the input emptied, but the ID in the console is the SAME each time **like the first clicked button**. For your comment about the termination of events, i meant by that if i can UNBIND the event to the clicked button. – 1heone Nov 30 '21 at 12:30
  • `that the other buttons doesn't behave the same (DOM is not updated)`...because your changes are incomplete...you still have a reference to "#submitComment" when you disable the button. I assume it'll be the same with customComment. You need to target the clicked element (or in the case of the comment, the element with the right class, nearest to the clicked element - jQuery has functions for doing that fairly easily) – ADyson Nov 30 '21 at 12:53
  • `but the ID in the console is the SAME each time like the first clicked button`...I don't see how this would be possible unless the data-id for every button contained all the same data to begin with. Here's a demo based on your code, showing that the `id` part of the code should work: https://jsfiddle.net/qx96ga3w/ - click on each of the three buttons, and it'll show you the correct data-id value for that button. – ADyson Nov 30 '21 at 12:57
  • `if i can UNBIND the event to the clicked button.`...yes you can use `.off` in jQuery to remove event handlers. – ADyson Nov 30 '21 at 12:58
  • @ADyson your code in jsfiddle ist about 3 different buttons. In my code there is only one Button with dynamic data-id projected from the database: ```data-id="```. That is why your code is straight forward. I cannot do the same, because in my project everything should loaded dynamically from the Database, even the Buttons. – 1heone Nov 30 '21 at 17:41
  • `In my code there is only one Button`...no there isn't because `foreach($data as $d) {` makes the PHP output multiple copies of it. So each one should have a different ID. My example merely shows what the jQuery will be confronted with after the PHP has finished running and makes lots of buttons in your page. – ADyson Nov 30 '21 at 17:45
  • Anyway it is not working. I don't understand why when any random button is clicked the first time it is working!!! then when i click on any other button it will not be considered (JQuery function not fired) only after i refresh the page manually then click again on any other button, then it works again... weird – 1heone Nov 30 '21 at 19:22
  • Anyway it is not working. I don't understand why when any random button is clicked the first time it is working!!! then when i click on any other button it will not be considered (JQuery function not fired) only after i refresh the page manually then click again on any other button, then it works again... weird – 1heone Nov 30 '21 at 19:22
  • That is weird, and it doesn't reflect the code you've shown. Provide a [mre] of that issue and we can help you solve it. – ADyson Nov 30 '21 at 19:59
  • That is weird, and it doesn't reflect the code you've shown. Provide a [mre] of that issue and we can help you solve it. – ADyson Nov 30 '21 at 19:59

1 Answers1

-1

You said you have "bunch of buttons.", I see only 1 in your code.

But if you have bunch of buttons with same class but different id, this code will work.

$('.myupdatebtn').each(function(){
$(this).on('click', function() { 
    var id = $(this).data('id');
    $.ajax({ 
      url: 'includes/updatestatus.php', 
      type: 'POST', 
      data: {id:id}, 
      dataType: 'html', 
      success: function(data)
      { 
        if (data) 
        { 
          $('#submitComment').attr("disabled", true); 
          $('#customComment').val("");
          $('#updatemsg-'+id).html("TERMINATED").removeClass('badge-danger').addClass('badge badge-success'); 
          console.log(id);
        } 
        else 
        { 
          $('#customContent').load("custom/static/error.html"); 
         } 
       }, 
       error: function(jqXHR, textStatus, errorThrown)
       { 
         $('#customContent').html("ERROR MSG:" + errorThrown); 
       } 
    }); 
});
})    

Give appropriate ids to buttons, so that your updatestatus.php works correctly.

$('.mybtn').each(function(){
  $(this).click(function(){
    alert("You clicked the button with id '"+this.id+"' call ajax do whatever");
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<h2>Bunch of buttons right?</h2>

<button id="1" class="mybtn">btn1</button><br/>
<button id="2" class="mybtn">btn1</button><br/>
<button id="3" class="mybtn">btn1</button><br/>
<button id="4" class="mybtn">btn1</button><br/>
<button id="5" class="mybtn">btn1</button><br/>

I couldn't understand what you meant by this 'Is there a way to terminate the JQuery event after each iteration (Button pressed for every menu item) and make it available again to be executed?', but as I know you need an active event listener, which triggers all the time button is clicked?

And one more thing I noticed, you are using if(data){//code} but what data?, you are not returning anything from php file, return something.

 <?php

    include("db.php");
    $id = $_POST['id'];
    $query = "UPDATE mytable SET status='TERMINATED' WHERE id='$id'";
    if(mysqli_query($conn, $query)) echo "1";
    else echo "2";
  ?>

Then use if(data === 1) {//do task} else if(data === 2){//Do else task}.

halfer
  • 19,824
  • 17
  • 99
  • 186
Mohammed Khurram
  • 616
  • 1
  • 7
  • 14
  • This will disable the wrong button afterwards (since you didn't change the reference to "submitButton". It will also likely clear the wrong comment field. And how is this code different to the OP's? I can't spot any changes, so if you made any, you'll need to point them out. It's unclear how you think this is solving the OP's current problem (which, if you've read the comments, you'll see is now rather vague and unspecified, notwithstanding the disabling issue I've already pointed out to you and to them). – ADyson Dec 01 '21 at 09:03
  • `I see only 1 in your code`...yes but the PHP `foreach` loop means that the code is likelky to generate multiple buttons into the finished HTML page (and that's what jQuery has to deal with). I already explained this to the OP in this comment: https://stackoverflow.com/questions/70168333/jquery-event-executed-only-once/70181220#comment124048505_70168333 . Did you read the comment thread before posting? – ADyson Dec 01 '21 at 09:04
  • Lol yaah sorry @ADyson I didn't see the `foreach` i guess my bad, but I think handling click event for each may fix this issue. – Mohammed Khurram Dec 01 '21 at 09:05
  • Oh I see what you've done now. Why do you think it would solve it, exactly? Give an explanation. But no, this is functionally no different to the OP's current code. jQuery will already bind the event handlers correctly using `on` with a class selector. (If it didn't, millions of people's code across the world would be very broken, and lots of the examples in the jQuery documentation would be wrong). In fact, again if you read the comments you'll see I already made a JSFiddle which proves it. – ADyson Dec 01 '21 at 09:13
  • Tip: if you need to comment in an answer that you didn't understand part of the question, it is generally best to refrain from answering. There isn't much value in capturing that lack of knowledge in an answer! Instead, if you can, seek clarifications in the comments. This way the resulting answer will be able to answer the problem fully, and it is likely to be more useful for future readers. – halfer Mar 26 '22 at 20:57