Trying to learn some php and mysql, so I’m working on a todo list where I want the todo tasks get a line-through when a checkbox that each task has is checked and removed again if unchecked.
like i have here:
I have made so i can make the line-through from a variable in database like this:
<input class="form-check-input form-check-input-todolist flex-shrink-0 my-1 me-2 form-check-input-undefined" type="checkbox" data-event-propagation-prevent="data-event-propagation-prevent" id="checkbox-todo-<?= $todoTask_Data['task_id'] ?>" <?php if($todoTask_Data['task_checked'] == 'true') {echo 'checked';} ; ?> />
Now I need to find out how i add the "true" variable to the task_checked column in mysqli when the checkboxes are clicked.
Not really worked with ajax/js much before, so its been very confusing figuring out how to do this. But I think i got the idea now, but still cant get this to work.
This is the script I got so fare
$(document).ready(function() {
$('.checkbox-todo').on('change', function() {
if (this.checked) {
var checkboxID = $(this).attr('id');
$.ajax({
url: "update_TodoTask.php",
method: "POST",
data: { checkboxID: checkboxID },
success: function(response) {
}
});
}
});
});
And inside update_TodoTask.php i got something like this:
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['checkboxID'])) {
$checkboxID = $_POST['checkboxID'];
header('Location: test.php');
}
Here is the html code: https://pastecode.io/s/zw4thpoe
But I don’t even think it is communication with update_TodoTask.php when pressed. should it not be triggering the header location when i press a checkbox?
I’m not sure im telling the ajax script which checkbox in the todo list is pressed correctly?
Can anyone tell me what I’m doing wrong here?
Update:
I am now able to add true to my task_checked collomn in the DB when i click the checkmarks using this:
$(document).ready(function() {
$('.form-check-input-todolist').on('change', function() {
var checkboxID = $(this).attr('id');
let [c, t, id] = checkboxID.split('-');
$.ajax({
url: "update_TodoTask.php",
method: "POST",
data: {
checkboxID: checkboxID,
id: id, // the Integer portion of ID - useful for sql update statement
state: ( this.checked ? 1 : 0 ) // Boolean - is it checked? - useful for sql update statement
},
success: (res) => {
console.log(res);
},
error: (err) => {
console.log(`${err.statusText} - problem making AJAX request with ID: ${id}`)
}
});
});
});
My update_TodoTask.php looks like this:
#assumed mySQLi connection
if( $_SERVER['REQUEST_METHOD']=='POST' && isset(
$_POST['checkboxID'],
$_POST['id'],
$_POST['state'],
)){
$checkboxID = $_POST['checkboxID'];
$id = $_POST['id'];
$state = $_POST['state'];
$todo_task_checkmark_update = mysqli_query($conn, "UPDATE todo_tasks SET task_checked = 'true' WHERE task_id = $id");
};
Now when I click one of the checkmarks it updates my DB with "true" value in the task_checked column..
The last thing I need now is to remove the checkmarks from the DB when i uncheckmark a todo item.
I’ve tried doing something like the code below, but can’t get the isset thing to working:
#assumed mySQLi connection
if( $_SERVER['REQUEST_METHOD']=='POST' && isset(
$_POST['checkboxID'],
$_POST['id'],
$_POST['state'],
)){
$checkboxID = $_POST['checkboxID'];
$id = $_POST['id'];
$state = $_POST['state'];
$query = "SELECT task_checked FROM todo_tasks WHERE task_id = $id";
$result = $conn->query($query);
$row = $result->fetch_assoc();
$todoTask_checkmark_status = $row['task_checked'];
if (isset($todoTask_checkmark_status)) {
if ($todoTask_checkmark_status == false) {
$todo_task_checkmark_update = mysqli_query($conn, "UPDATE todo_tasks SET task_checked = 'true' WHERE task_id = $id");
} elseif ($todoTask_checkmark_status == true) {
$todo_task_checkmark_update = mysqli_query($conn, "UPDATE todo_tasks SET task_checked = 'false' WHERE task_id = $id");
}
};
};
I also tried the isset with $_POST[‘state’] but same problem.. It like it not even running the isset part..
What am I doing wrong?
2
Answers
To ensure that the database is updated to reflect the checked/unchecked/checked nature of the user’s choice you should send an AJAX request for each
change
event registered on each input element. The AJAX request should also send the checked value so that your can determine whether the table should still say checked or unchecked.You can explode the STRING id attribute to determine the actual integer value and also the
this.checked
boolean value – add those to the POST payload sent via AJAX.The PHP code then has the actual (presumably) ID value and a Boolean to be used in the SQL update statement.
Rather than worry about the Javascript
state
being a Boolean or String when posted it is easy to replace that with an integer 1 or 0 using simple ternary operator.Your PHP then might be a little like this:
You would not want to use the
header
call at the end of the script as you have sent an AJAX request rather than a regular HTTP GET request so it will not be honoured. Instead, send meaningful data back to the AJAX callback function – the callback can be used to update the DOM somehow or let the user know they did a good/bad things etcI have a number of places where I want to indicate that something has been handled. I do it by graying out the option using
style.opacity
This does not even go back to the server. At the same time, I do send an AJAX command to the server to persist the change in the database.
Is the above your real case? Or might the need for the strikethrough come from some other process? If it is the latter, my answer does not apply.
The JS approach (with strikethrough or gray-out) has two advantages: A second click can be programmed to undo, and the screen does not jump around. (Previously, I was deleting the text or image — that led to a ‘bad user experience’ of the screen jumping around in seemingly random ways.
For both do and undo, here is some JS code:
(Adapt it for strikethrough if you prefer.)