How to make a for in a script tag?

Asked

Viewed 50 times

1

Guys, I’m trying to create a page on my site that shows me title, description and the location of the record of some occurrences. When I access the page, I load through a <c:forEach> all occurrences with their proper parameters. Occurrences are sent inside a list via Servlet to a JSP, which shows them.

My problem is that to load the map with the location of the occurrence, I need to execute a tag <script> who has no body. The tag loads the files and, at the end of the upload, calls a javascript function, present on the page, using a callback="function()".

Because I am using this tag to load and call the function that shows my map with the occurrence location, I need it to be executed in a forEach, for or anything else that helps me loop. I thought about doing it with scriptlet or JSTL, but I couldn’t right away. Can anyone help me? I’m using the Google Maps javascript API.

JSP loading the location:

    <%@page pageEncoding="ISO-8859-1"%>
            <%@include file="includes/cabecalho.html"%>
            <%@include file="includes/navmenu.jsp"%>
            <div class="centralizado jumbotron">
                <div class="card-deck">
                    <!--Panel-->
                    <div class="row">
                        <c:forEach var="ocorrencia" items="${ocorrencias}">
                            <div class="col-md-4">
                                <div style="padding: 10px;" class="card">
                                    <div style="padding: 10px;" class="card-body">
                                        <h5 class="card-title">${ocorrencia.tituloOcorrencia}</h5>
                                        <p class="card-text">${ocorrencia.descricaoOcorrencia}</p>
                                        <div style="position: relative; width: 100%;height: 300px" id="map"></div>
                                        <input type="number" id="lat" value="${ocorrencia.latitudeOcorrencia}" hidden/>
                                        <input type="number" id="lng" value="${ocorrencia.longitudeOcorrencia}" hidden/>
                                        <br>
                                    </div>
                                    <div class="card-footer">
                                        <small class="text-muted">${ocorrencia.usuario_fk_ocorrencia.nomeUsuario} em ${ocorrencia.dataOcorrencia}</small>
                                    </div>
                                </div>
                            </div>
                        </c:forEach>
                    </div>
                </div>
            </div>
            <script>
                // Initialize and add the map
                function initMap() {

                    //Attribuition for lat and lng to var
                    var lat = parseFloat(document.getElementById('lat').value);
                    var lng = parseFloat(document.getElementById('lng').value);
                    // The location of Uluru
                    var uluru = {lat: parseFloat(lat), lng: parseFloat(lng)};
                    // The map, centered at Uluru
                    var map = new google.maps.Map(
                        document.getElementById('map'), {zoom: 15, center: uluru});
                    // The marker, positioned at Uluru
                    var marker = new google.maps.Marker({position: uluru, map: map});
                }
            </script>
            <!--Load the API from the specified URL
            * The async attribute allows the browser to render the page while the API loads
            * The key parameter will contain your own API key (which is not needed for this tutorial)
            * The callback parameter executes the initMap() function
            -->
            <!--Preciso do loop nesta tag-->
            <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAUWfu8L-5YIKUDXV812EM3tBZhrK0uDY4&callback=initMap"></script>

            <%@include file="includes/footer.jsp"%>

Some information that might be helpful to me: https://developers.google.com/maps/documentation/javascript/tutorial

1 answer

1


See this field with the ids lat, lng and map within the forEach? So this means that you will generate several elements with these same ids. However, the value of the field id should be unique.

The solution to make ids unique is to concatenate a number after them. And then, you can use these numbers in the function initMap.

To get a unique number in each iteration, you can use the field varStatus of forEach.

Your code should look like this:

<%@ page pageEncoding="UTF-8" %>
<%@ include file="includes/cabecalho.html" %>
<%@ include file="includes/navmenu.jsp" %>
<script type="text/javascript">
    // Initialize and add the map
    function initMap(n) {
        // Attribuition for lat and lng to var
        var lat = parseFloat(document.getElementById('lat-' + n).value);
        var lng = parseFloat(document.getElementById('lng-' + n).value);
        var mapElement = document.getElementById('map-' + n);

        // The location of Uluru
        var uluru = {lat: parseFloat(lat), lng: parseFloat(lng)};
        // The map, centered at Uluru
        var map = new google.maps.Map(mapElement, {zoom: 15, center: uluru});
        // The marker, positioned at Uluru
        var marker = new google.maps.Marker({position: uluru, map: map});
    }
</script>
<div class="centralizado jumbotron">
    <div class="card-deck">
        <!--Panel-->
        <div class="row">
            <c:forEach var="ocorrencia" items="${ocorrencias}" varStatus="loop">
                <div class="col-md-4">
                    <div style="padding: 10px;" class="card">
                        <div style="padding: 10px;" class="card-body">
                            <h5 class="card-title">${ocorrencia.tituloOcorrencia}</h5>
                            <p class="card-text">${ocorrencia.descricaoOcorrencia}</p>
                            <div style="position: relative; width: 100%; height: 300px" id="map-${loop.index}"></div>
                            <input type="number" id="lat-${loop.index}" value="${ocorrencia.latitudeOcorrencia}" hidden/>
                            <input type="number" id="lng-${loop.index}" value="${ocorrencia.longitudeOcorrencia}" hidden/>
                            <br>
                        </div>
                        <div class="card-footer">
                            <small class="text-muted">${ocorrencia.usuario_fk_ocorrencia.nomeUsuario} em ${ocorrencia.dataOcorrencia}</small>
                        </div>
                    </div>
                </div>
                <script type="text/javascript">
                    function initMap${loop.index}() {
                        initMap(${loop.index});
                    }
                </script>
                <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAUWfu8L-5YIKUDXV812EM3tBZhrK0uDY4&callback=initMap${loop.index}"></script>
            </c:forEach>
        </div>
    </div>
</div>

<%@ include file="includes/footer.jsp" %>

Note that the ${loop.index} will become an iteration counter, and with it, it is possible to load this Google Maps script once for each iteration.

The loop is a variable of the type javax.servlet.jsp.jstl.core.LoopTagStatus, an object type that serves to provide data on the iteration of the forEach. one of his methods is getIndex(), which is the result of the call to ${loop.index}. You can see more about this object here and that question in Soen.

Another detail: I recommend using UTF-8 instead of ISO-8859-1. The ISO-8859-1 format is outdated and obsolete and will give you problems when someone tries to put text in Chinese or emojis on your page. Better to prevent and change everything to UTF-8 now than to remedy later when problems start to appear.

  • Thank you so much for the help. The index of the.index loop is something like a "reserved variable", right?

  • @Welberduarte I edited the answer to explain this better.

  • Beauty. Thanks @Victorstafusa.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.