Excel-like Updating a table without a button in PHP and AJAX - javascript

I need to update a row of a table. So when I click on a cell, I want it to be transformed into text box, so I used this:
<td contenteditable></td>
And then, when the content of a <td> is changed, I need to send it through AJAX to update it in the server without clicking on a button, so it will use the .change(function()).
I tried to get the content changed into a variable:
$("TD").change(function()
{
//Here I want to set the row ID:
var rowid = '<?php echo $row['id'] ?>';
var name = $("#emp_name").val();
var position = $("#position").val();
var salary = $("#salary").val();
$.ajax
({
url: 'update.php',
type: 'POST',
data: {dataId: rowid, data1: name, data2: position, data3: salary},//Now we can use $_POST[data1];
dataType: "text",
success:function(data)
{
if(data=="success")
{
//alert("Data added");
$("#before_tr").before("<tr><td>"+emp+"</td><td>"+pos+"</td><td>"+sal+"</td></tr>");
$("#emp_name").val("");
$("#position").val("");
$("#salary").val("");
}
},
error:function(data)
{
if(data!="success")
{
alert("data not added");
}
}
});
});
The problem is how to know which row is changed to send it via AJAX ? I am not getting any errors even when data not updated.
Here is the update.php code:
try
{
$rowid = $_POST['dataId'];
$emp_name = $_POST['data1'];
$pos = $_POST['data2'];
$sal = $_POST['data3'];
$upd = "UPDATE emp SET name = :emp_name, position = :pos, sal = :sal WHERE id = :rowid";
$updStmt = $conn->prepare($upd);
$updStmt->bindValue(":rowid", $rowid);
$updStmt->bindValue(":emp_name", $emp_name);
$updStmt->bindValue(":pos", $pos);
$updStmt->bindValue(":sal", $sal);
$updStmt->execute();
echo "success";
}
catch(PDOException $ex)
{
echo $ex->getMessage();
}
HTML:
<tbody>
<?php
$sql = "SELECT * FROM employee";
$stmt=$conn->prepare($sql);
$stmt->execute();
$res=$stmt->fetchAll();
foreach($res as $row){
?>
<tr id=""<?php echo $row['id'] ?>"">
<td contenteditable><?php echo $row['emp_name'] ?></td>
<td contenteditable><?php echo $row['position'] ?></td>
<td contenteditable><?php echo $row['salary'] ?></td>
</tr>
<?php } ?>

When loading your data with PHP you need to keep the row id in your html:
<tr id="<?php echo $yourList["id"]; ?>">
<td contenteditable></td>
</tr>
Then in your javascript you can catch it using the parent() jquery function
$("TD").change(function()
{
//Here I want to set the row ID:
var rowid =$(this).parent().attr("id");
......
UPDATE
Check this example, I have added listeners to detect contenteditable td changes, I think you shall add it too , refer to this contenteditable change events for defining proper change events on contenteditable fields.
Explanation:
The contenteditable does not trigger change events, this work around is used to detect the focus event of the td using jquery on method and event delegation. The original content is saved in the td jquery data object $this.data('before', $this.html()); . Then when the user leaves the field or triggers any of the events 'blur keyup paste input', the current content is compared to the content in the data object, if it differs, the change event of the td is triggered.
$(document).ready(function(){
$('table').on('focus', '[contenteditable]', function() {
var $this = $(this);
$this.data('before', $this.html());
return $this;
}).on('blur keyup paste input', '[contenteditable]', function() {
var $this = $(this);
if ($this.data('before') !== $this.html()) {
$this.data('before', $this.html());
$this.trigger('change');
}
return $this;
});
$("TD").change(function()
{
//Here I want to set the row ID:
var rowid = $(this).parent().attr("id");
$("#res").html(rowid);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1" width="500px">
<tr id="1222">
<td contenteditable></td>
</tr>
<tr id="55555">
<td contenteditable></td>
</tr>
</table>
Row Id : <span id="res"></span>

<tr row_id="<?php echo $row['id'] ?>"> ></tr>
In Your Ajax
var rowid = $(this).attr('row_id');

Related

Ajax request doesn't return a response

I need a little help for my ajax request. I think i don't get the good value but i have tried more methods, without success.
The purpose is when we click on Info client, another array is displayed with more info. But I always have the last id added and not the id's clicked's row.
My HTML :
<div>
<table id="list_client" border=1>
<tr>
<td>#</td>
<td>Nom</td>
</tr>
<?php
require 'config.php';
$clients = $db->query('SELECT * FROM client');
foreach ($clients as $client) : ?>
<tr id="<?php echo $client["id_client"]; ?>">
<td><?php echo $client["id_client"]; ?></td>
<td><?php echo $client["nom_client"]; ?></td>
<td><button name="info" id="info" type="button" onclick="display_info(<?php echo $client['id_client']; ?>);">Info client</button></td>
<td><button type="button" onclick="hide_info(<?php echo $client['id_client']; ?>);">Masquer client</button></td>
<?php endforeach; ?>
</table>
</div>
My JavaScript and Ajax request:
function display_info() {
$("#info").click(function () {
var datas = {
action: "read",
id_client: $("#id_client").val(),
};
$.ajax({
type: "GET",
url: "function.php",
async: true,
data: datas,
dataType: "json",
cache: false,
}).done(function (result) {
console.log("result");
$("#result").text("response : " + JSON.stringify($result));
});
});
}
#result is a div besides the array. (to test)
My PHP function :
function read() {
global $db;
$id_client = $_GET['id_client'];
$client = "SELECT * FROM client WHERE id_client = '$id_client'";
$query = $db->prepare($client);
$query->bindValue(':id_client', $id_client, PDO::PARAM_INT);
$query->execute();
$result = $query->fetch();
echo json_encode($result);
}
I think I am close but no idea what I did wrong.
Issues:
#1 <tr id="<?php echo $client["id_client"]; ?>">
In the above code, how will you dynamically get the id of the client when trying to use it in Javascript?
#2 <td><button name="info" id="info" type="button" onclick="display_info(<?php echo $client['id_client']; ?>);">Info client</button></td>
Above code will make all buttons have same id which is info. id needs to unique per HTML element.
#3 id_client: $("#id_client").val(),.
There is no element with id as id_client.
#4 function display_info() { $("#info").click(function () {.
You are attaching an onclick as well as a click event listener which is not required. Do either of them and not both but I would recommend the latter one.
#5 $client = "SELECT * FROM client WHERE id_client = '$id_client'";
You aren't preparing the query here with a placeholder but rather just adding the retrieved id in the query which is very unsafe since we can't trust user input.
#6 You also missed a closing tr tag.
Solution:
For issue #1, no need to attach an id attribute to a tr tag at all.
For issue #2, make info a class name instead of the id and remove onclick as it isn't needed.
For issue #3, we would get the id_client value from the data-id attribute which we will attach to the respective info button.
For issue #4, encapsulating click event listener inside display_info is not needed. We can directly attach the listener.
For issue #5, we will add a placeholder for id_client to properly bind our primitive value inside the query.
For issue #6, we will add a closing tr tag.
Snippets:
Frontend:
<div>
<table id="list_client" border=1>
<tr>
<td>#</td>
<td>Nom</td>
</tr>
<?php
require 'config.php';
$clients = $db->query('SELECT * FROM client');
foreach ($clients as $client):
?>
<tr>
<td><?php echo $client["id_client"]; ?></td>
<td><?php echo $client["nom_client"]; ?></td>
<td><button data-id="<?php echo $client["id_client"]; ?>" type="button" class="info">Info client</button></td>
<td><button type="button" class="hide_client" data-id="<?php echo $client["id_client"]; ?>">Masquer client</button></td>
</tr>
<?php endforeach; ?>
</table>
</div>
<script>
$(".info").click(function(){
var datas = {
action: "read",
id_client: $(this).attr('data-id'),
};
$.ajax({
type: "GET",
url: "function.php",
data: datas,
dataType: "json",
cache: false,
}).done(function(result) {
console.log("result");
$("#result").text("response : " + JSON.stringify($result));
});
});
$('.hide_client').click(function(){
let client_id = $(this).attr('data-id');
// do your thing here
});
</script>
Backend:
<?php
function read() {
global $db;
$id_client = $_GET['id_client'];
$query = $db->prepare("SELECT * FROM client WHERE id_client = :id_client");
$query->bindValue(':id_client', $id_client, PDO::PARAM_INT);
$query->execute();
$result = $query->fetch();
echo json_encode($result);
}
Not sure if that's the error you're having, but
$client = "SELECT * FROM client WHERE id_client = '$id_client'";
should probably read
$client = "SELECT * FROM client WHERE id_client = :id_client";
as the binding of the prepared statement doesn't work otherwise.
Other than that: Can you check which results you get from your select query and if that's the result you expect?
you are giving the clientid over to the function display_info, you don't need to read it out with jquery... just change
function display_info() {
to
function display_info(clientid) {
and change the
var datas = {
action: "read",
id_client: $("#id_client").val(),
};
to
var datas = {
action: "read",
id_client: clientid,
};

Delete a table row with dynamic id that comes from DB using ajax

I have a table that it's content is comes from database.When I click on the delete button I want to delete that row with Ajax. Actually right now it's working but with a bug and that is all of the rows get deleted when I click on the button and then if I refresh , the row that I was deleted is gone and other rows are shown.But as I said it needs a refresh.Any solution would be appreciated .
$('.dashboard-subscribe-form').submit(() => {
event.preventDefault();
const currentHiddBtn = $('.dash-subscribe-form-btn');
console.log(currentHiddBtn.closest('tr'));
const userCaution = confirm('Want to delete this quote?');
if (userCaution) { //If admin insists to delete the row
const deleteId = $('.dash-subscribe-form-btn').attr('value');
$.ajax({
type: "POST",
url: "delete-subscribe.php",
dataType: "json",
data: {
deleteId: deleteId
},
success: (data) => {
if (data.code === '200') {
console.log('It works!');
currentHiddBtn.closest('tr').css('background', 'tomato');
currentHiddBtn.closest('tr').fadeOut(1200, () => {
});
} else if (data.code === '404') {
alert('An error occurred!Please try again.');
}
}
});
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<tbody>
<?php
$count = 1;
$sqlCommand = "SELECT * FROM `kq0b3_subscribe`";
$sqlCommandPrepare = $pdoObject->prepare($sqlCommand);
$sqlCommandPrepare->execute();
while ($result = $sqlCommandPrepare->fetch()) {
?>
<tr id="row-<?php echo $result['id']; ?>">
<td class="dashboard-records">
<?php echo $count; ?>
</td>
<td class="dashboard-records">
<?php echo $result['email']; ?>
</td>
<td>
<form action="" method="post" class="dashboard-subscribe-form">
<input id="<?php echo $result['id']; ?>" type="hidden" class="dash-subscribe-form-btn" name="hidden-del" value='<?php echo $result[' id ']; ?>'/>
<button type="submit" name="sub-del-btn" class="btn btn-danger del" value='<?php echo $result[' id ']; ?>'> Delete
</button>
</form>
</td>
</tr>
<?php
$count++;
}
?>
</tbody>
delete-subscribe.php:
<?php
require_once('config.php');
$delete_row = $_POST['deleteId'];
if($delete_row){
$sqlCommand = "DELETE FROM `kq0b3_subscribe` WHERE `id` = ?";
$sqlCommandPrepare = $pdoObject->prepare($sqlCommand);
$result = $sqlCommandPrepare->execute([
$delete_row
]);
/*The json_encode() must be after all of our calculation codes and DB query codes and...(It must be the
last line of code) */
echo json_encode(['code' => '200'], JSON_THROW_ON_ERROR, 512);
}
else {
echo json_encode(['code' => '404'], JSON_THROW_ON_ERROR, 512);
}
UPDATE2: now I'm using :
$('#row-' + deleteId).css('background', 'tomato');
$('#row-' + deleteId).fadeOut(1200, () => {
});
but the new problem is : it doesn't matter which button I click, the forst row is deleted (when any button is clicked , in the console , the id of the first row-button is printed , not the actual id that I was clicked. ).How can I fix this one?
I think the main issue, in this case, is using CSS classes as a selector and it seems to be selecting the first instance no matter which item you are clicking.
The code causing this is:
const deleteId = $('.dash-subscribe-form-btn').attr('value');
You want to be getting the target input from the event object passed from your .submit().
I have created a jsfiddle with an example that could be adapted to your code but here is a quick preview of jQuery part.
$('.dashboard-subscribe-form').submit((event) => {
event.preventDefault()
console.log(event.target.elements[0]["value"])
$('#result-from-click').html("Input Value: " + event.target.elements[0]["value"])
})
It is selecting the first element within the elements array which is the input. If you want the button you can use event.target.elements[1]
You could then also use the value returned to remove the <tr> with the same id instead of finding the nearest. This could be done in the success part of your ajax call without doing a refresh.

How to post MySql row variable using Javascript on button click

I have a html table populated with mysql data. Each row has an id (e.g 001, 002 etc). Within each table row I have created a button. I'd like to be able to post the current time in milliseconds (working fine) as well as the relevant id of the row (which the button clicked is in) to an Ajax file. My Ajax file works fine I just can't get the right id to post.
I have tried using <?php echo $row=$REQUEST ['id']?> but it only returns the first value in the table not the respective one.
<table width="100%" border="1" style="border-collapse:collapse;">
<thead>
<tr>
<th><strong>ID Number</strong></th>
<th><strong>Class</strong></th>
<th><strong>Crew</strong></th>
<th><strong>Start</strong></th>
<th><strong>Finish</strong></th>
</tr>
</thead>
<tr>
<td align="center"><?php echo $row["number"];?></td>
<td align="center"><?php echo $row["class"];?></td>
<td align="center"><?php echo $row["crew"]?></td>
<td> <input type="hidden" id="boatnumber" name="custId" value="<?php echo $row["number"];?>"<button id="startbutton" type="submit" class="newbutton"></td></tr>
<script>
$(document).ready(function() {
var delay = 2000;
$('.newbutton').click(function(e){
e.preventDefault();
var d = new Date();
var start = d.getTime()
var id = $('#id').val();
if(start == ''){
$('.message_box').html(
'<span style="color:red;">Enter Your Username!</span>');
$('#start').focus();
return false;
}
var boatnumber = $('#boatnumber').val();
if(boatnumber == ''){
$('.message_box').html('<span style="color:red;">Enter Your Boat
ID!`</span>');
$('#boatnumber').focus();
return false;
}
$.ajax({
type: "POST",
url: "ajax/start.php",
data: "start="+start+"&boatnumber="+boatnumber,
beforeSend: function() {
$('.message_box').html(
'<img src="Loader.gif" width="25" height="25"/>');},
success: function(data){
setTimeout(function() {
$('.message_box').html(data);}, delay);
}
});
});
});
</script>
It only sends the id of the first row in the table not the id of the row where the button (that is clicked) is.
You are getting the value of an element with the ID of #boatnumber, you can't have multiple elements with the same ID.
A better way maybe to use a data attribute on the button that holds the number and then retreive it in your script.
HTML:
<button type="submit" class="newbutton" data-number="<?php echo $row['number'] ?>">
Script:
var boatnumber = $(this).data('number);

Update specific row of table of multiple entries

I have a table of customers. Each customer has a first and a last name. The two text fields of the table are editable. So users can update the information when they press Save. The problem is that I cannot get the specific row information,I only get the first row results
I tried to match to the names with the input field but I had no success.
<?php foreach($customer as $each){ ?>
<td class="first_name" id="first" contenteditable="true"><?php echo
$each['first_name']; ?></td>
<td class="last_name" id="last" contenteditable="true"><?php echo
$each['last_name']; ?></td>
<td > <button type="button" onclick="save('<?php echo $each['first_name'];?
>','<?php echo $each['last_name'];?>');" >Save</button></td>
<? } ?>
<script type="text/javascript">
function save(first,second) {
<?php foreach($customer as $each){?>
var first_name = "<?php echo $each['first_name']?>";
var last_name = "<?php echo $each['last_name']?>";
if (first_name==first && last_name == second){
var fname = document.querySelectorAll(".first_name");
console.log(fname[0]);
}
<?php } ?>
}
</script>
You would have to use a different query selector. Assign a classname or an attribute to the elements you want to select (e.g name for querying with .name) then querySelectorAll method will return an array of the elements that matched your query.
The main problem that I see is that you create unnecessary foreach loop inside a javascript function using php.
You can dynamically create your table and the contents inside it, that's fine. But the javascript does not care about that and you should not create javascript with php. So I would do it this way.
I wrap the td's in tr's cause i'm assuming you are putting that data in tr.
<?php foreach($customer as $each){ ?>
<tr class="customer-row">
<td class="first_name" contenteditable="true"><?php echo
$each['first_name']; ?></td>
<td class="last_name" contenteditable="true"><?php echo
$each['last_name']; ?></td>
<td><button type="button" class="save">Save</button></td>
</tr>
<? } ?>
Then outside the php foreach loop i would create my script.
<script type="text/javascript">
var saveBtn = document.querySelectorAll(".save");
for(var i = 0; i < saveBtn.length; i++) {
// attach click event to every button.
saveBtn[i].addEventListener("click", function() {
var _this = this;
var _tr = _this.closest(".customer-row");
var fname = _tr.querySelector(".first_name").innerText;
var lname = _tr.querySelector(".last_name").innerText;
console.log("Name: ", fname + " " + lname");
// below you can implement your check name logic...
}
}
</script>
I'm not 100% sure if my js will not throw errors, but it should give you an indication that you should separate your server-side from client-side logic.

PHP Ajax delete a record from table

Some strange problem occurred. I am trying to delete a record from a table by using AJAX but whenever I click the delete button it is sending the ID of the last row in the table each time instead of that specific ID which I want to delete to my delete-process.php page. Now I checked that the PHP page and codes are just working fine. When I did console.log(dataString) I got to see that no matter which Delete button I click I get the ID of the last field only.
Code
<table class="table table-hover table-striped">
<thead>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Date</th>
<th>Action</th>
</thead>
<tbody>
<?php while($si = $stmt->fetch()){ extract($si); ?>
<tr>
<td><?php echo $ct_id; ?></td>
<td><?php echo $ct_name; ?></td>
<td><?php echo $ct_email; ?></td>
<td><?php echo $ct_phone; ?></td>
<td><?php echo date('jS M, Y (h:i a)', strtotime($ct_date)); ?></td>
<td>
<form method="post" action="">
View
<input type="text" value="<?php echo $ct_id; ?>" class="ctid">
<input type="submit" value="Delete" class="btn btn-danger btn-fill delete">
</form>
</td>
</tr>
<?php } ?>
</tbody>
AJAX
$(document).ready(function() {
$(".delete").click(function() {
var dataString = {
id: $(".ctid").val()
};
console.log(dataString);
var $submit = $(this).parent().find('.delete');
$.confirm({
title: 'Confirm!',
content: 'Are you sure you want to delete this message?',
buttons: {
confirm: function () {
$.ajax({
type: "POST",
//dataType : "json",
url: "delete-process.php",
data: dataString,
cache: true,
beforeSend: function(){
$submit.val("Please wait...");
},
success: function(html){
$('.message').html(html);
if($('.message').find('#responseBox').hasClass('alert-success')){
$.alert(html);
setTimeout(function(){
window.location.replace("support.php<?php if(!empty($_GET['ids'])){ ?>?ids=<?php echo $_GET['ids']; } ?>");
},2000);
}
}
});
},
cancel: function(){}
}
});
return false;
});
});
I did not include PHP code because the error is detected in console.log(dataString) as every button clicked is sending the same ID. Please help.
$(".ctid") will return an array containing all of the elements with that class.
You are only interested in the sibling to the clicked button so you should use $(this).prev().
$(this) will reference the clicked button.
.prev() selects the immediately proceeding sibling.
$(".delete").click(function() {
var dataString = {
id: $(this).prev().val()
};
...
});
As you are creating the table rows using loop so the class ctid is repeated. so when you are accessing this like this id: $(".ctid").val(). It will return all the elements having class ctid. So change your script like this
var dataString = {
id: $(this).siblings('.ctid').val()
};
Of course it is selecting the same ctid since you don't distinguish between forms. You can distinguish like this:
var dataString = {
id: $(this).closest('form').find('.ctid').val()
};
"closest" navigates to the form and then find the ctid that is contained in the form.
When you do this:
$(".ctid").val()
Which matching element are you expecting? The code doesn't specify, and ".ctid" matches multiple elements. But since it can only return a single value, it's simply returning the last matching one. Essentially, you need to specify which matching element you want.
One way to do this is by navigating the DOM from the clicked button to the nearest matching element. Perhaps by navigating up to a single common parent element and then finding the target element therein. Something like this:
$(this).closest("form").find(".ctid").val()
Starting from the clicked element which raised the event (this), it navigates up to the containing <form> and then searches for the matching ".ctid" within that form. Then gets the value from only that element.
You can inspect to check each button value is getting unique or not
You can achieve that without using ajax use below code
Delete

Categories

Resources