I think you have a little confusion regarding the use of req.param
and req.query
.
In your backend, as you say, you originally receive a parameter ( :taskId
) and pass that parameter to the remove
of your controller Task
.
Now, your requirements have changed and you must pass not one, but several taskId
to perform a batch process.
To solve this you have some alternatives, I will mention one that will help you solve your problem and at the same time it will give you an idea of how req.param
and req.query
are used.
Another thing that I can notice, in your frontend code you declare query_string
but then I do not see that you use it.
Let's start:
The first thing we are going to do is create a route in the backend that captures '/api/tasks'
without including any parameter:
// nueva ruta en el backend, la pondremos antes de la ruta antigua.
router.route('/api/tasks')
.delete(async (req, res, next) => {
// Ahora verificamos si la URI contiene la query que esperamos
if (!req.query.taskId) {
return res.status(400).json({
message: 'Nada para procesar'
});
}
// Nuestra API espera una query con la clave taskId
// y que contenga una lista de id válidos para realizar
// el proceso por lotes.
let taskId = []; // aqui almacenaremos los id
let id = ''; // aqui construiremos los id desde el string, carácter por carácter
for (let index in req.query.taskId) {
// Los valores vendrán separados por coma
// (los puedes separar como gustes, pero prefiero
// usar el viejo CSV: Comma Separated Value)
if (req.query.taskId[index] !== ',') {
id = id.concat(req.query.taskId[index]); // almacenamos el carácter en id.
} else {
taskId.push(id); // Encontramos una comma, guardamos el id
id = '' // reiniciamos para volver a empezar
}
}
// Si todo va bien, tendremos el array con los taskId a procesar.
// Ahora podemos procesar los datos:
await Task.deleteMany({ id : { $in : taskId } });
res.json({ status: 'Task deleted' });
});
We already have the route in our backend, we just need to modify in the frontend to create the correct URI that contains the taskId
in the form of query
:
deleteTask(taskId) {
// Asumo que taskId es un array con los "id"
// Dado que este es tu código, no tengo mucho que explicarte
// salvo que he quitado el string "taskId=" y
// cambié el nombre de la variable de "pair" a "ids"
var ids = taskId.map(function (value) { return encodeURIComponent(value) });
// aqui tampoco debo explicarte mucho porque también es tu código, solo que he cambiado "&" por ","
var query_string = ids.join(",");
// como ves, aqui paso el query string en la URI
// y si te das cuenta, tu mismo habías intuído que
// debías usar una query, dado el nombre de tu variable
//Una cosa que debes observar es cómo se pasa un query en una URI.
fetch('/api/tasks?taskId=' + query_string, {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(data => {
this.getTasks();
});
},
I hope that with this you solve the problem. As I say it is not the only way to do it, but if it avoids you less modifications in your frontend.
Notice that when you use req.param
you pass the route in the following way: '/api/tasks/:taskId'
of this form Express understands that you are passing one (1) parameter. Already in your API you must have the controller that manages the parameter.
On the other hand, if you want to use req.query
you must do it in the following way: '/api/tasks?query1=value1&query2=value2&...&queryN=valueN'
. You should note that a query
is a consistent list of key=value
and every key
must have a different name.
In this specific case, as we do not know how many taskId
we are going to erase, then I decided to pass them as a CSV in a single key called taskId
.
However, if your taskId
are too long and too many, this is not the best method to do so, since you are facing problems with the size of the URI that your server can handle.
You can read more at link
Here is an excerpt from the Section "3.2.1 General Syntax":
The HTTP protocol does not place any a priori limit on the length of
to URI. Servers MUST be able to handle the URI of any resource they
serve, and SHOULD be able to handle URIs of unbounded length if they
provide GET-based forms that could generate such URIs. A server
SHOULD return 414 (Request-URI Too Long) status if a URI is longer
than the server can handle (see section 10.4.15).
Note: Servers ought to be cautious about depending on URI lengths
above 255 bytes, because some older client or proxy
implementations might not properly support these lengths.
Edit:
As you put in your comment, your values of taskId
will be id
of Mongo, therefore it is not appropriate to send them by means of the URI to the server, since if you send many id
the URI would be too long .
What you can do is send them in the body
of your request, in the following way:
deleteTask(taskId) {
// Asumo que taskId es un array con los "id"
// Ahora apuntamos directamente a la ruta '/api/tasks'
fetch('/api/tasks', {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(taskID) // <=== Aqui enviamos la data en el 'body' del mensaje.
})
.then(res => res.json())
.then(data => {
this.getTasks();
});
},
Now we must change the code in the backend to receive and process the data properly:
router.route('/api/tasks')
.delete(async (req, res, next) => {
// Nuestra data viene en 'req.body', verificamos
if (!req.body) {
return res.status(400).json({
message: 'Nada para procesar'
});
}
// Almacenamos la data de body en 'taskId'
const taskId = req.body;
// Si quieres ver el contenido de taskId:
for (let index in taskId) {
console.log('index: ', index, ' taskId: ', taskId[index]);
}
// Ya podemos procesar la data
await Task.deleteMany({ id : { $in : taskId } });
res.json({ status: 'Task deleted' });
});
This is already enough to get what you need.
I hope you have been helpful.