I run into the following problem:
I have an element <select>
that should display a list of comments that contains an item in the database. A click event performs a query in the database and updates the content of the element <select>
, but it displays the list before the content is updated and I have to make a second click so that it already shows the updated content.
What I would like is for the list to be displayed updated from the first click.
I also have the problem that the content is updated on the initial click that displays the list as well as on the click that selects the option... and the latter is superfluous.
I have the following...
The element <select>
within the view.
<select class="custom-select" name="read-selector-comment" id="read-selector-comment" data-userid="{{_id}}">
<option selected>Selecciona comentario del menú</option>
</select>
The following listeners are activated after loading the page
// Eventos que controlan la selección y visión de comentarios
const $UserCommentsSelectorTab = document.getElementById(
'read-selector-comment',
);
if ($UserCommentsSelectorTab) {
// Actualiza items de la lista a cada click
$UserCommentsSelectorTab.addEventListener('click', refreshCommentsList);
// Mustra contenido selecionado
$UserCommentsSelectorTab.addEventListener('change', viewComment);
}
A click event on the element executes the following function that performs a search in the database and with the result enters the elements <option>
in<select>
async function refreshCommentsList(event) {
const $commentList = event.currentTarget;
// Solicitando actualizacion de datos al servidor.
const r = await fetch(`/user/comments/${$commentList.dataset.userid}`, {
headers: new Headers(),
method: 'POST',
});
if (r.ok) {
const resp = await r.json();
let template = '<option selected>Selecciona comentario del menú</option>';
// Generando plantilla actualizada para el selector de comentarios
resp.forEach((element) => {
template += `<option name="comment-selected" value='{"text": "${element.text}",
"tags": "${element.tags}",
"user": "${element.user}",
"date": "${pretiffyDate(element.date)}"
}'"> ${pretiffyDate(element.date)} - ${element.user}}</option>`;
});
// Añade los elementos actualizados
$commentList.innerHTML = template;
} else {
swal('Error', 'Error al actualizar comentarios', 'error');
}
}
The change event on the element <select>
updates other elements in the view by displaying the information.
/** Muestra el comentario seleccionado */
function viewComment(event) {
const $title_box = document.getElementById('comment-title');
const $text_box = document.getElementById('text-comment-box');
const $tags_box = document.getElementById('tags-comment-box');
const comment = JSON.parse(event.currentTarget.value);
// Título
$title_box.innerText = `${comment.date} - ${comment.user}`;
// Texto
$text_box.innerText = comment.text;
// Tags
const tags = comment.tags.split(',');
let tagsTemplate = '';
tags.forEach((element) => {
tagsTemplate += `<span class="badge badge-success m-2">${element}</span> `;
});
$tags_box.innerHTML = tagsTemplate;
}
In the end, I found this solution for this specific problem:
In the application, to see comments, a modal is opened that contains a form with:
<select>
that contains the list of user comments.<textbox>
for the text and the tags.div
with buttons to edit and delete the comment.I use a
helper
tohandlebars
generate the content for me by<select>
getting all the comments from the database. This helps me so that with the initial load of the modal the updated list of comments is displayed.But...
From the same modal you can access some buttons for
editar
oreliminar
the comment. If any changes are made, the list becomes stale even if the modal is closed and opened again.To solve this...
On the
script.js
client side I put the same function as on thehelper
, and after doing a$form.reset()
, I call it to update the content of the<select>
every time a comment is created, edited or deleted.