Вопрос или проблема
Я создал menu-edit.pug, чтобы показать свою форму редактирования, надеюсь, что пользователи нажмут на ссылку меню, перейдут на эту страницу редактирования и внесут некоторые изменения. При отправке формы обновленное значение будет сохранено и произойдет перенаправление на страницу меню.
Мой код: страница редактирования готова, но что-то не так с моими действиями по редактированию/отправке. Когда я отправляю обновленные данные в браузере, создается новая ссылка вместо перезаписи существующей.
Страница menu-edit
block layout-content
div.content
h1.page-title Редактировать ссылку меню
//- /admin/menu/edit/submit будет местом, куда отправляются данные формы
form(method="post", action="/admin/menu/edit/submit")
input(type="hidden", name="linkId", value=editLink._id)
div
label(for="wgt") Вес:
input(type="number", id="wgt", name="weight", value=editLink.weight)
div
label(for="href") URI:
input(type="text", id="href", name="path", value=editLink.path)
div
label(for="link-name") Текст ссылки:
input(type="text", id="link-name", name="name", value=editLink.name)
button(type="submit") Обновить ссылку
Мой index.js выглядит следующим образом:
app.get("/admin/menu/edit", async (request, response) => {
if (request.query.linkId) {
let linkToEdit = await getSingleLink(request.query.linkId);
let links = await getLinks();
response.render("menu-edit", { title: "Редактировать ссылку меню", menu: links, editLink: linkToEdit });
}
else {
response.redirect("/admin/menu");
}
});
app.post("/admin/menu/edit/submit", async (request, response) => {
let id = request.query.linkId;
let idFilter = { _id: new ObjectId(id)};
let link = {
weight: parseInt(request.body.weight),
path: request.body.path,
name: request.body.name
};
await editLink(idFilter, link);
response.redirect("/admin/menu");
})
async function getSingleLink(id) {
db = await connection();
const editId = { _id: new ObjectId(id) };
const result = await db.collection("menuLinks").findOne(editId);
return result;
}
async function editLink(filter, link) {
db = await connection();
const options = { upsert: true };
// Укажите обновление для установки значения для поля link
let updateLink = {
$set: {
weight: link.weight,
path: link.path,
name: link.name
}
};
let result = await db.collection("menuLinks").updateOne(filter, updateLink, options);
// Вывод количества соответствующих и измененных документов
// https://www.mongodb.com/docs/drivers/node/current/usage-examples/updateOne/#std-label-node-usage-updateone
console.log(
`${result.matchedCount} документ(ов) соответствует фильтру, обновлено ${result.modifiedCount} документ(ов)`,
);
}
Ответ или решение
Ваша проблема заключается в неправильном использовании идентификатора ссылки при отправке данных формы на сервер. В функции обработки POST-запроса для обновления линков вы извлекаете linkId
из request.query
, однако форма отправляет linkId
как скрытое поле, которое доступно через request.body
. Это объясняет, почему при отправке формы создаётся новая запись вместо обновления существующей.
Вот так можно изменить ваш код для правильной обработки обновления:
1. Изменение маршрута для обработки обновления
Вместо извлечения linkId
из запроса, вам нужно получить его из request.body
.
app.post("/admin/menu/edit/submit", async (request, response) => {
let id = request.body.linkId; // Изменено на получение из request.body
let idFilter = { _id: new ObjectId(id) };
let link = {
weight: parseInt(request.body.weight),
path: request.body.path,
name: request.body.name
};
// Обновление ссылки с использованием правильного фильтра
await editLink(idFilter, link);
response.redirect("/admin/menu");
});
2. Убедитесь, что ваша функция editLink корректно обновляет данные
Вы уже используете updateOne
с правильным фильтром и обновлением, так что остальная часть вашей функции сохранения изменений выглядит хорошо:
async function editLink(filter, link) {
db = await connection();
const options = { upsert: false }; // Убедитесь, что upsert отключен
let updateLink = {
$set: {
weight: link.weight,
path: link.path,
name: link.name
}
};
let result = await db.collection("menuLinks").updateOne(filter, updateLink, options);
console.log(
`${result.matchedCount} документ(ов) соответствует фильтру, обновлено ${result.modifiedCount} документ(ов)`,
);
}
3. Общее замечание
Убедитесь, что у вас корректно настроен middleware для обработки express
и что вы используете body-parser
для получения данных из тела запроса. Например:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
Заключение
С внесёнными изменениями ваш код должен корректно обрабатывать обновления, и данные будут изменяться вместо создания новых записей. Не забудьте проверить консоль на вывод ошибок, которые могут возникнуть, чтобы убедиться, что все операции выполняются успешно.