No popup when trying to add ability to click on traffic icons and view traffic information

Hi All

I am trying to add the ability to click on the traffic icons to view the traffic information on my map.

I have been mostly following the examples of the two below SDK live examples:

  • Traffic Incidents List
  • Custom Incident Markers and Popups

I am encountering an issue with the below function where when it runs after you click on an icon the ‘feature’ is coming through as undefined:

function addPopup(feature, detailsFeatures) {
var details;
if (detailsFeatures) {
detailsFeatures.forEach(function(detailFeature) {
if (detailFeature.properties.id === feature.properties.id) {
details = detailFeature.properties;
}
});
}
closePopup();
if (details) {
state.popup = new tt.Popup({
offset: [0, -20], className: ‘tt-popup’
})
.setLngLat(feature.geometry.coordinates)
.setHTML(createCustomPopupHTML(feature.properties, details))
.addTo(map);
}
}

Full html code below:

<!doctype html>

<meta charset="utf-8">

<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no">

<link rel='stylesheet' type='text/css' href='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.21.3/maps/maps.css'>

<link rel='stylesheet' type='text/css' href='./tomtomMapAssets/ui-library/index.css'/>

<link rel='stylesheet' type='text/css' href='./tomtomMapAssets/ui-library/icons-css/poi.css'/>

<link rel='stylesheet' type='text/css' href='./tomtomMapAssets/ui-library/icons-css/traffic-incidents.css'/>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js'></script>

<script src='https://cdn.jsdelivr.net/npm/javascript-debounce@1.0.1/dist/javascript-debounce.min.js'></script>

<script src='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.21.3/maps/maps-web.min.js'></script>

<script src='https://api.tomtom.com/maps-sdk-for-web/cdn/6.x/6.21.3/services/services-web.min.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/tail.select.min.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/formatters.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/info-hint.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/foldable.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/mobile-or-tablet.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/search/side-panel.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/traffic/incidents-details-manager.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/traffic/incident-marker.js'></script>

<script type='text/javascript' src='./tomtomMapAssets/js/search/dom-helpers.js'></script>

<script type="text/javascript">

    $(document).ready(function () {

        const queryString = window.location.href;

        const urlParams = (new URL(queryString).searchParams);

        const lat = urlParams.get('lat')

        const lng = urlParams.get('lng')

        const tomtomMapApiKey = 'XXXXXXXXXXX';

        const TRAFFIC_INCIDENTS_STYLE = 's0';

        let tomtomMap = tt.map({

            key: tomtomMapApiKey,

            container: 'map',

            center: [lng, lat],

            zoom: 15,

            dragPan: true, //!isMobileOrTablet()

            stylesVisibility: {

                trafficIncidents: true,

                trafficFlow: true

            }

        });

        var state = {

            popup: undefined,

            popupIncidentLayer: undefined,

            featureId: undefined,

            loadingPopup: false

        };

        var errorHint = new InfoHint('error', 'bottom-center', 5000).addTo(document.getElementById('map'));

        var loadingHint = new InfoHint('info', 'bottom-center').addTo(document.getElementById('map'));

        loadingHint.setMessage('Loading...');

        tomtomMap.addControl(new tt.FullscreenControl());

        tomtomMap.addControl(new tt.NavigationControl());

        tomtomMap.on('load', function() {

            getIncidentLayers().forEach(function(layerId) {

                tomtomMap.on('click', layerId, function(event) {

                    onIncidentClick(event, layerId);

                });

            });

            performIncidentDetailsRequest().then(function(incidentDetailsResponse) {

                if (incidentDetailsResponse.length) {

                    var feature = incidentDetailsResponse[0];

                    tomtomMap.setCenter(feature.geometry.coordinates);

                    tomtomMap.setZoom(15);

                }

                state.popup = new tt.Popup({ className: 'tt-popup', offset: 20 })

                    .setHTML('Click on any incident marker to open a popup.')

                    .setLngLat(tomtomMap.getCenter())

                    .addTo(tomtomMap);

            }).catch(function(error) {

                errorHint.setMessage(error);

            }).finally(function() {

                loadingHint.hide();

            });

        });

        function onIncidentClick(event, layerId) {

            if (state.loadingPopup) {

                return;

            }

            state.loadingPopup = true;

            var feature = event.features[0];

            state.featureId = feature.properties.id;

            tomtomMap.panTo(feature.geometry.coordinates, {duration: 200});

            performIncidentDetailsRequest().then(function(incidentDetailsResponse) {

                addPopup(feature, incidentDetailsResponse);

                state.popupIncidentLayer = tomtomMap.getLayer(layerId);

            }).catch(function(error) {

                errorHint.setMessage(error);

            }).finally(function() {

                state.loadingPopup = false;

            });

        }

        function getIncidentLayers() {

            return tomtomMap.getStyle().layers.filter(function(layer) {

                return layer.source === 'vectorTilesIncidents' && layer.type === 'symbol';

            }).map(function(layer) {

                return layer.id;

            });

        }

        function performIncidentDetailsRequest() {

            return tt.services.incidentDetailsV5({

                key: tomtomMapApiKey,

                boundingBox: tomtomMap.getBounds(),

                fields: `{

                    incidents {

                        type,

                        geometry {

                            type,

                            coordinates

                        },

                        properties {

                            id,

                            iconCategory,

                            magnitudeOfDelay,

                            events {

                                description,

                                code,

                                iconCategory

                            },

                            from,

                            to,

                            length,

                            delay,

                            roadNumbers

                        }

                    }

                }`

            }).then(data => {

                return data.incidents.map(el => ({

                    geometry: {

                        coordinates: el.geometry.coordinates[0],

                        type: 'Point'

                    },

                    properties: el.properties,

                    type: el.type

                }));

            });

        }

        function addPopup(feature, detailsFeatures) {

            var details;

            if (detailsFeatures) {

                detailsFeatures.forEach(function(detailFeature) {

                    if (detailFeature.properties.id === feature.properties.id) {

                        details = detailFeature.properties;

                    }

                });

            }

            closePopup();

            if (details) {

                state.popup = new tt.Popup({

                    offset: [0, -20], className: 'tt-popup'

                })

                .setLngLat(feature.geometry.coordinates)

                .setHTML(createCustomPopupHTML(feature.properties, details))

                .addTo(map);

            }

        }

        function closePopup() {

            if (state.popup) {

                state.popup.remove();

            }

            state.popup = undefined;

            state.popupIncidentLayer = undefined;

            state.incidentId = undefined;

        }

        function createCustomPopupHTML(properties, details) {

            var photo = photosMapping[properties.description_0] || photosMapping.default;

            var description = details.events[0].description || properties.description_0;

            return (

                '<div class="tt-traffic-details -column">' +

                    '<div class="details-header">' +

                        '<img class="custom-img -' +

                        details.incidentSeverity + '" src="../assets/images/custom-incident-markers/' + photo + '">' +

                        '<div>' +

                            (details.roadNumbers.length ?

                                '<div class="tt-road-shield">' + details.roadNumbers + '</div>' : '') +

                        '</div>' +

                    '</div>' +

                    '<div class="tt-traffic-description">' +

                        '<div class="tt-incident-category">' + description + '</div>' +

                    '</div>' +

                    createCustomPopupDetailsContentHTML(details) +

                '</div>'

            );

        }

        function createCustomPopupDetailsContentHTML(details) {

            if (!details) {

                return '';

            }

            return (

                '<div class="details-content">' +

                    '<div>' +

                        (details.delay ?

                            '<div><label>Delay:</label> ' +

                                Formatters.formatToDurationTimeString(details.delay) + '</div>' :

                            '') +

                        '<div>' +

                            '<label>Traffic length:</label> ' +

                            Formatters.formatAsMetricDistance(details.length) +

                        '</div>' +

                    '</div>' +

                    '<div><label>From:</label> ' + details.from + '</div>' +

                    '<div><label>To:</label> ' + details.to + '</div>' +

                '</div>'

            );

        }

    });

</script>
<div id="map" class="map"></div>

Hello :slight_smile:
I run your code, but couldn’t reproduce the issue :frowning: The feature object is defined whenever I click on it:

example

Is the feature object undefined for you every time you click, or it happens in some specific circumstances?