I’d say that part of the problem is that you’re looping over the elements in evento
. Assuming that listaEventos
looks like
[
{
"Event": 100,
"Desc": "ejkbjkberwjkber",
},
{
"Event": 200,
"Desc": "ejkbjkberwjkber",
},
]
then {% for key, value in evento.items() %}
will output Desc as its own table row and Event as its own table row.
To display each row as Event/Description:
<tbody>
{% for evento in listaEventos %}
<tr>
<td>
<button>
{{ evento.Event }}
</button>
</td>
<td>{{ evento.Desc }}</td>
</tr>
{% endfor %}
</tbody>
To show the next event in a series, for example CardID 20, you might want to include more information for each element in listaEventos e.g.
[
{
"Event": 100,
"Desc": "ejkbjkberwjkber",
"Start": 1,
"End": 2
},
{
"Event": 200,
"Desc": "ejkbjkberwjkber",
"Start": 1,
"End": 5
},
]
Also, to minimise the HTML rendered, I’d move the modal to a separate code block outside each table row. That way, you can use a JavaScript function to populate the contents of the modal.
Bringing it all together:
<div class="container mb-5">
<table border="1" id="tablaEventos" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>Evento</th>
<th>Descripción</th>
</tr>
</thead>
<tbody>
{% for evento in listaEventos %}
<tr>
<td>
<button onclick="showModal(this, {{ evento.Event }})">
{{ evento.Event }}
</button>
</td>
<td>{{ evento.Desc }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Modal -->
<div class="modal fade" data-bs-backdrop="static" id="modal_Event" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel"></h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<button type="button" class="btn btn-outline-primary btn-sm col-md-3">
<svg width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/>
</svg>
Validación Anterior
</button>
<!-- I used showModal(100) with data-current-result='1' here to demonstrate fetching the next result. Change here to match your logic -->
<button type="button" class="btn btn-outline-primary btn-sm col-md-3 ms-auto" data-current-result="1" onclick="showModal(this, 100)">
Siguiente Validación
<svg width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
</svg>
</button>
</div>
<div class="container mt-3 mb-3" id="modalContent">
<!-- Modal content goes here -->
</div>
</div>
<div class="modal-footer">
<div class="container-fluid">
<div class="row">
<button type="button" class="btn btn-primary col-md-4">Evento anterior</button>
<!-- I used showModal(200) here to demonstrate fetching the next event. Change here to match your logic -->
<button type="button" class="btn btn-primary col-md-4 ms-auto" onclick="showModal(this, 200)">Siguiente Evento</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- CDN MODAL-->
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<!-- CDN DATA TABLES-->
<script src="//code.jquery.com/jquery-3.5.1.js"></script>
<script src="//cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>
<script src="//cdn.datatables.net/1.12.1/js/dataTables.bootstrap5.min.js"></script>
<script>
$(document).ready(function () {
$('#tablaEventos').DataTable({
"language":{
"url": "//cdn.datatables.net/plug-ins/1.12.1/i18n/es-ES.json"
}
});
});
const eventInfo = {{ eventInformation|tojson }}; // Use the value of eventInformation as a JS variable
----------
function showModal(elementClicked, eventId) {
var eventModalElement = document.getElementById('modal_Event');
// Use getOrCreateInstance to prevent 'ghosting' that would result if a new modal were created
var eventModal = bootstrap.Modal.getOrCreateInstance(eventModalElement);
var currentResult = elementClicked.getAttribute("data-current-result");
if (currentResult) {
// Use the Start and End values to determine whether to increase the value of the currentResult or go to the next event
// if currentResult less than end currentResult + 1
// else eventId + 100 and currentResult = 1
}
// Fetch the modal content element
var modalContent = document.getElementById("modalContent");
// Set the HTML of the modal content element
modalContent.innerHTML = getEventModalHtml(eventId, resultId);
// Show the
eventModal.show();
}
function getEventModalHtml(eventId, resultId) {
html = "";
for (event of eventInfo) {
// The following is just an example to return data
// Use the eventId and resultId (if it exists) to filter
if (event["Event"] === eventId) {
var eventStr = "Event " + event["Event"] + " Result " + event["Result"] + "<br>"
html += eventStr;
}
}
return html;
}
</script>
Hope this helps.
For more reading:
Bootstrap modals: https://getbootstrap.com/docs/5.0/components/modal
Jinja tojson
filter: https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.tojson
After hours of testing I managed to fix it, the only problem I had was that the modal ID was being overwritten. To go from one event to another with the button “Siguiente Evento” I have solved it in part also in the same way, thanks to loop.index0 that jinja2 offers this is the new way to generate modals so when clicking on the button “Siguiente Evento” it simply shows the modal with the next ID.
<div class="container mb-5">
<table border="1" id="tablaEventos" class="table table-striped table-bordered" style="width:100%" align="center">
<thead>
<tr>
<th>Evento</th>
<th>Descripción</th>
</tr>
</thead>
<tbody>
{% for eventInformation in listEventInformation %}
<tr>
<td>
<a href="" data-bs-toggle="modal" data-bs-target="#modal_{{ loop.index0 }}">
{{ eventInformation.Evento }}
</a>
</td>
<td>{{ eventInformation.Descripción }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Modal -->
{% for eventInformation in listEventInformation %}
<div class="modal fade" data-bs-backdrop="static" id="modal_{{ loop.index0 }}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">{{ eventInformation.Evento }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="container mt-3 mb-3">
<ul class="disc">
{% for eventKey, eventValue in eventInformation.items() %}
<li>{{ eventKey }}: {{ eventValue }}</li>
{% endfor %}
</ul>
</div>
</div>
<div class="modal-footer">
<div class="container-fluid">
<div class="row">
<button type="button" class="btn btn-primary col-md-4" href="#modal_{{ loop.index0 - 1 }}" data-bs-toggle="modal" data-bs-dismiss="modal">Evento anterior</button>
<button type="button" class="btn btn-primary col-md-4 ms-auto" href="#modal_{{ loop.index0 + 1 }}" data-bs-toggle="modal" data-bs-dismiss="modal">Siguiente Evento</button>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
I’m using flask for my website application. It consists of reading certain files that contain a large number of dictionaries. I extracted that information on a list of dictionaries that looks like something like this (It’s really importante to know that some dictionaries have the same value for the key “Event” but different information):
[
{
"Evento": 100
"Descrición": "This is a event 100 description",
"CardID": 10,
"Title": "This is a event 100 title",
"Result": 1,
},
{
"Evento": 107
"Descrición": "This is a event 107 description",
"CardID": 20,
"Title": "This is a event 107 title",
"Result": 3,
},
{
"Evento": 107
"Descrición": "This is a event 107 description",
"CardID": 30,
"Title": "This is a event 107 title",
"Result": 1,
},
{
"Evento": 118
"Descrición": "This is a event 118 description",
"CardID": 50,
"Title": "This is a event 118 title",
"Result": 10,
}
...
]
In the flask app i render a template which has a table, which iterates over other list with another information related with the dictionary from above but with less information (the event and a brief description). The first value of the body table has a link to open a modal which would show the information of the event and depending the button that is presses, it should show the information of the next event with the same number or the information of the next event.
I can’t add images since is one of my first questiones but the modal that is shown when the link on the table is clicked, shows the information from all the events but i only want the information from one event (100 in this case) and, when the button “Siguiente validación ->” is pressed it should show the information of the next event 100 and, when “Siguiente Evento” is pressed it should show the information of the next event on the table (e.g.: 200)
This is the template code for the table and the modal:
{% extends './layout.html' %}
{% block body %}
<div class="container mb-5">
<table border="1" id="tablaEventos" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th>Evento</th>
<th>Descripción</th>
</tr>
</thead>
<tbody>
{% for eventInformation in listEventInformation %}
<tr>
<td>
<a href="" data-bs-toggle="modal" data-bs-target="#modal_Event{{ eventInformation.Evento }}">
{{ eventInformation.Evento }}
</a>
</td>
<td>{{ eventInformation.Descripción }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<!-- Modal -->
{% for eventInformation in listEventInformation %}
<div class="modal fade" data-bs-backdrop="static" id="modal_Event{{ eventInformation.Evento }}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">{{ eventInformation.Evento }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<button type="button" class="btn btn-outline-primary btn-sm col-md-3">
<svg width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/>
</svg>
Validación Anterior
</button>
<!-- I used showModal(100) with data-current-result='1' here to demonstrate fetching the next result. Change here to match your logic -->
<button type="button" class="btn btn-outline-primary btn-sm col-md-3 ms-auto" data-current-result="1" onclick="showModal(this, 100)">
Siguiente Validación
<svg width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
</svg>
</button>
</div>
<div class="container mt-3 mb-3" id="modalContent">
<!-- Modal content goes here -->
{% for eventKey, eventValue in eventInformation.items() %}
<li>{{eventKey}}: {{eventValue}}</li>
{% endfor %}
</div>
</div>
<div class="modal-footer">
<div class="container-fluid">
<div class="row">
<button type="button" class="btn btn-primary col-md-4">Evento anterior</button>
<!-- I used showModal(200) here to demonstrate fetching the next event. Change here to match your logic -->
<button type="button" class="btn btn-primary col-md-4 ms-auto" data-bs-toggle="modal" data-bs-target="#modal_Event{{ eventInformation.Evento }}" onclick="showModal(this, 200)">Siguiente Evento</button>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<!-- CDN MODAL-->
<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<!-- CDN DATA TABLES-->
<script src="//code.jquery.com/jquery-3.5.1.js"></script>
<script src="//cdn.datatables.net/1.12.1/js/jquery.dataTables.min.js"></script>
<script src="//cdn.datatables.net/1.12.1/js/dataTables.bootstrap5.min.js"></script>
<script>
$(document).ready(function () {
$('#tablaEventos').DataTable({
"language":{
"url": "//cdn.datatables.net/plug-ins/1.12.1/i18n/es-ES.json"
}
});
});
const eventInfo = {{ eventInformation }}; // Use the value of eventInformation as a JS variable
----------
function showModal(elementClicked, eventId) {
var eventModalElement = document.getElementById('modal_Event');
// Use getOrCreateInstance to prevent 'ghosting' that would result if a new modal were created
var eventModal = bootstrap.Modal.getOrCreateInstance(eventModalElement);
var currentResult = elementClicked.getAttribute("data-current-result");
if (currentResult) {
// Use the Start and End values to determine whether to increase the value of the currentResult or go to the next event
// if currentResult less than end currentResult + 1
// else eventId + 100 and currentResult = 1
}
// Fetch the modal content element
var modalContent = document.getElementById("modalContent");
// Set the HTML of the modal content element
modalContent.innerHTML = getEventModalHtml(eventId);
// Show the
eventModal.show();
}
function getEventModalHtml(eventId) {
html = "";
for([eventKey, eventValue] of Object.entries(eventInfo)) {
if (eventInfo["Evento"] === eventId) {
html += <li>''+eventKey+': '+eventValue</li>>;
}
}
return html;
}
</script>
{% endblock %}
The real problem I think is how to show only the dictionary you are iterating over in the list and when you press the button, show the information of the next iteration.
First of all, thanks for replying @M69k65y. I am trying to recreate what you have told me but with the real data, the problem I am running into is that in the function “showModal”, I can’t figure out how the currentResult and data-current-result parameter works. Right now I have managed to display the info for each event in a modal, but, for some reason, the info displayed is always the same, which doesn’t make much sense because in a separated python script it worked properly for me. Anyways, I updated the code and the list of dictionaries.