2

I would like to have multiple markers on the same map with Symfony and UX Map! I've read the documentation but can't find the solution there! At the moment, I can get all the markers but on different maps with this code:

<div class="map">
    {% for signalement in signalements %} 
    {{ ux_map(                
        center : [47.65, 1.50],
        zoom: 7,                   
        markers: [                    
            {   
                position: [signalement.structure.latitude, signalement.structure.longitude],                         
                title: signalement.structure.nom
            },                 
        ],                
        attributes: {
            class: 'mapimap',
            style: 'height: 35rem; width: 30rem',
        }                
        ) 
    }}
    {% endfor %}
</div>

I need to be able to loop only the markers part, but I don't see how to do it!


Thanks A.L. for your reply! I tried it myself, but it doesn't work :(

I get this error message:

A mapping key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token “operator” of value “%”.

Here's what I did:

<div class="map">           
   {{ ux_map(                
       center : [47.65, 1.50],
       zoom: 7,
       {% set markers = [] %}
       {% for signalement in signalements %} 
           {% set markers = markers|merge([{
              'position' : [signalement.structure.latitude, signalement.structure.longitude],
              'title' : signalement.structure.nom
            }])
            %}
       {% endfor %}
       attributes: {
          class: 'mapimap',
          style: 'height: 35rem; width: 30rem',
       }) 
    }}
</div>

Or maybe I didn't understand the reply correctly or used it wrong :(

2
  • 2
    See symfony.com/bundles/ux-map/current/index.html#add-markers Commented Oct 24 at 14:56
  • I saw you updated the question. You have to move the and {% set … %} and {%for … %} blocks before {{ ux_map(, you can't write Twig code in a Twig tag like this. Also, you never pass the markers to ux_map. I added an example in the answer. Commented Oct 27 at 18:00

1 Answer 1

3

It looks like the input data looks like this:

{% set signalements = [
    {'structure': {'latitude': 50, 'longitude': 1, 'nom': 'ACME'}},
    {'structure': {'latitude': 51, 'longitude': 2, 'nom': 'Symfony'}}
] %}

We can create an array and loop over the data to prepare the markers (thanks Javier Eguiluz for this answer):

{% set markers = [] %}

{% for signalement in signalements %}
    {% set markers = markers|merge([{ 'position': [signalement.structure.latitude, signalement.structure.longitude], 'title': signalement.structure.nom}]) %}
{% endfor %}

Code to show the data (for debugging only):

<ul>
{% for marker in markers %}
    <li>{{ marker.position|join(',') ~ ' → ' ~ marker.title }}</li>
{% endfor %}
</ul>

Then you can have only one map ux_map (remove the loop) and pass the markers with markers: markers,, like this:

{{ ux_map(                
    center : [47.65, 1.50],
    zoom: 7,
    markers: markers,          
    attributes: {
        class: 'mapimap',
        style: 'height: 35rem; width: 30rem',
    }
) }}

Example on Twig Playground.


The same logic can be done in PHP in the controller: populate the markers array before passing it to Twig:

$markers = [];

foreach ($signalements as $signalement) {
    $markers[] = [
        'position' => [$signalement->structure->latitude, $signalement->structure->longitude],
        'title' => $signalement->structure->nom,
    ];
}

// or just
$markers = array_map(function($value) {
    return [
        'position' => [$value->structure->latitude, $value->structure->longitude],
        'title' => $value->structure->nom,
    ];
}, $signalements);

You will have to call the correct getters to retrieve the data of your objects.

Example on 3v4l.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh! I didn't realize I had to do two parts! It works perfectly! Thank you :)
@d3LTa7 That's great! Please consider accepting this answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.