javascript - JavaScript Fetch() 不区分表单的更新和删除功能
问题描述
我有一个当前在服务器上使用 PHP/MySQL 处理的表单,它在前端使用 JavaScript fetch() API,这样当详细信息提交到数据库时,页面不会在表单提交时重新加载。
表单本身位于一个循环中,该循环将表单的多个实例输出到页面上。
为了使 JavaScript 工作,它依赖于以下 PHP(我将在问题末尾显示更详细的代码)
if($_SERVER['REQUEST_METHOD'] == 'POST') {
// PHP to process form details
}
javascript是:
var forms = document.querySelectorAll('form');
forms.forEach(item => {
item.addEventListener("submit", function (evt) {
evt.preventDefault();
const formData = new FormData(this);
fetch("upload-details.php", {
method: 'post',
body: formData
}).then(function(response){
return response.text();
}).catch(function (error){
console.error(error);
})
// remove item after form details submitted
item.remove();
})
})
我现在希望添加一个也适用于 JS fetch API 的删除按钮。我遇到的问题是,我无法让 JS Fetch 区分何时更新表单详细信息和何时删除记录?
我试过改变这个:
if($_SERVER['REQUEST_METHOD'] == 'POST') {
// PHP to process form details (both update and delete)
}
为此(无济于事):
if(isset($_POST['update'])) {
// PHP to process form details
}
if(isset($_POST['delete'])) {
// PHP to process form details
}
当我关闭 JS fetch() API 代码时,从 PHP / MySQL 的角度来看,下面的代码的行为完全符合预期(即它相应地更新和删除记录)。
更详细的代码:
<?php
isset($_REQUEST['username']) ? $username = $_REQUEST['username'] : header("Location: login.php");
// the following variable is already fetched with PHP from the database
// it is added as a value to a hidden input element in the HTML form shown below
$db_image_id = htmlspecialchars($row['image_id']);
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$image_title = $_POST['image-title'];
$image_tags = $_POST['image-tags'];
$image_id = $_POST['image-id']; // value attribute from hidden form element
if(empty(trim($image_title))){
$error[] = "Image Title cannot be blank";
}
if (!isset($error)) {
try {
$sql = "UPDATE imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE image_id = :image_id";
$stmt = $connection->prepare($sql);
$stmt->execute([
':image_title' => $image_title,
':image_tags' => $image_tags,
':image_id' => $image_id
]);
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
} else {
// give values an empty string to avoid an error being thrown before form submission if empty
$image_title = $image_tags = "";
}
}
//---- DELETE DETAILS
if(isset($_POST['upload-details-delete'])) {
$image_id = $_POST['image-id']; // 'value' attribute from hidden form element
try {
$sql = "DELETE FROM `lj_imageposts` WHERE image_id = :id";
$stmt = $connection->prepare($sql);
$stmt->execute([
':id' => $image_id
]);
} catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
// data is fetched with PHP to add to the form
//(I haven't included this code because there is a lot of values outputted onto the form, and when the JavaScript fetch() is turned off it all works OK)
while ($row = $stmt->fetch()) {
?>
<!-- form that holds the update and delete elements -->
<div class="upload-details-component">
<form method="post" enctype="multipart/form-data">
<button name="delete">Delete</button>
<div class="upload-details-image-wrapper">
<!-- ** image is outputted here from database ** -->
</div>
<div class="edit-zone">
<div class="form-row">
<label>Image Title</label>
<input type="text" name="image-title" placeholder="Image Title" >
</div>
<div class="form-row">
<label>Image Tags</label>
<textarea type="text" name="image-tags"></textarea>
</div>
<div class="form-row">
<input type="submit" name="upload" value="COMPLETE UPLOAD">
</div>
</div>
<input type="hidden" name="image-id" value="<?php echo $db_image_id?>">
</form>
</div>
<?php } ?>
解决方案
仅当用户单击它时才添加到 POST 数据中的提交按钮。由于您在 javascript 中收集表单数据,因此不会单击任何按钮,因此不包括它们。
您需要做的是找出单击了哪个提交按钮,并在收集表单数据之前手动添加带有此类信息的隐藏输入字段,或者注入表单数据本身:
var forms = document.querySelectorAll('form');
forms.forEach(item => {
item.addEventListener("submit", function(evt) {
evt.preventDefault();
const formData = new FormData(this);
formData.set(evt.submitter.name, evt.submitter.value);
console.log([...formData].join("|"));
})
})
<form>
<input name="test" value="blah">
<input type="hidden" name="hid" value="hidblah">
<button type="submit" name="update" value="upd">update</button>
<button type="submit" name="delete" value="del">delete</button>
</form>
由于并非所有浏览器都支持event.submitter
,因此您需要通过 onclick 事件跟踪单击了哪个按钮:
var forms = document.querySelectorAll('form');
forms.forEach(item => {
item.querySelectorAll('[type="submit"], button').forEach(button => {
button.addEventListener("click", e => item._button = button); //store this button in the form element
})
item.addEventListener("submit", function(evt, btn) {
evt.preventDefault();
const formData = new FormData(this);
if (this._button) //submitted by a button?
{
formData.set(this._button.name, this._button.value);
delete this._button; //this only needed if form can be submitted without submit button (aka submitted by javascript)
}
console.log([...formData].join("|"));
});
})
<form>
<input name="test" value="blah">
<input type="hidden" name="hid" value="hidblah">
<button type="submit" name="update" value="upd">update</button>
<button type="submit" name="delete" value="del">delete</button>
<button name="submit" value="sub">submit</button>
</form>
<form>
<input name="test2" value="blah2">
<input type="hidden" name="hid2" value="hidblah2">
<button type="submit" name="update2" value="upd2">update2</button>
<button type="submit" name="delete2" value="del2">delete2</button>
<button name="submit2" value="sub2">submit2</button>
</form>
推荐阅读
- pytorch - Pytorch data.random_split() 不会随机拆分
- python - ODEINT - 添加新方程时的不同结果
- amazon-web-services - 是否可以使用 python 在 codecommit 中获取特定文件的最后提交信息?
- python - 使用 multiprocessing.Pool 在 Python 中实现 Matlab 的 Parfor(多维数组的问题)
- python - 排序文件夹后缺少文件
- google-sheets - 如果 Google 表格的另一个单元格中有特定值,我如何创建一个条件来将一个值放入一个单元格中
- cmake - cmake:如何有条件地添加外部项目?
- visual-studio-code - 在 Visual Studio Code 中自定义 Jupyter Notebooks 的样式
- sql - PostgreSQL:使用窗口函数计数(*)超过()时按主键排序缓慢
- python - 在 Pandas 中翻转数据框并将一列的值保留为新行的值