2

How can I dynamically change the HTML content of a Leaflet popup using JavaScript?

I have text in the popup that I want to change when it's clicked:


map_layer = L.geoJSON(countries, {
    onEachFeature: this.country_clicked
}).addTo(this.map);

...

country_clicked = (country, layer) => {
    // I spread the popup's HTML over multiple lines for readability:
    layer.bindPopup("<p id='hide' onclick='show_hide()'>
                         Click me
                     </p>

                     <script>
                         function show_hide() {
                             document.getElementById('hide').innerHTML = 'New text...';
                         }
                     </script>"
                   );
}

The plain HTML part of the popup works fine, but when I click the paragraph text, my Angular throws an error:

Uncaught ReferenceError: show_hide is not defined
onclick map.component.css:1

I've seen this post but their solution makes the function run when the layer is clicked, not the popup content.

Is there a way for me to modify the popup HTML with JavaScript?

Edit, full Angular code:

map.component.ts:

export class MapComponent implements OnInit
{
    init_map()
    {
        this.map = L.map("map", { ... });

        this.map_layer = L.geoJSON(this.countries, {
            onEachFeature: this.country_clicked
        }).addTo(this.map);
    }

    ...

    country_clicked(country, layer)
    {
        layer.bindPopup('<p id="hide" onclick="show_hide(this, \'New text ...\')">
                             Click me
                         </p>');
    }

    show_hide(element, txt)
    {
        element.innerHTML = txt;
    }
}

But this still throws Uncaught ReferenceError: show_hide is not defined error.
I've tried putting the show_hide() function everywhere and it still can't be found by the popup:

  • Out of the Map class
  • Within the Map class
  • Within the country_clicked function
3
  • See stackoverflow.com/questions/13698975/… May 12, 2022 at 12:22
  • That post is for jquery, but I'm not using jquery. May 12, 2022 at 12:31
  • 1
    It doesn't matter. The point is that stuff in popups doesn't exist when you think it does, or where you think it does. That includes <script>s and stuff like rewriting the definition of a function in a given scope. May 12, 2022 at 15:02

2 Answers 2

2

Define your show_hide() function on global level and then call it with text parameter you want to replace current text with.

Code could then look something like this:

 function show_hide(element, txt) {
  element.innerHTML = txt;
 }

country_clicked = (country, layer) => {
  layer.bindPopup('<p id="hide" onclick="show_hide(this, \'New text ...\')">Click me</p>');
}
3
  • See my update above. I've tried adding the show_hide function everywhere but it still isn't being found. May 13, 2022 at 4:58
  • Sorry, but I'm not familiar with Angular and so I can't help you here.
    – TomazicM
    May 13, 2022 at 6:51
  • Thank you the help. I was able to find a solution, I submitted as an answer. May 25, 2022 at 8:29
2

For some reason, Angular wasn't detecting the show_hide() funtion, no matter where I tried putting it. But I was able to achieve what I wanted by embedding the code within the HTML onclick definition:

country_clicked(country, layer)
{
    // note the use of BOTH types of quotes: double ( " ) and single ( ' )
    // to create a string within a string
    const new_text = '"New text..."';
    //               ^ outer quotes must be OPPOSITE to the outer quotes below

    layer.bindPopup("<p onclick='this.innerHTML=" + new_text + "'>Click me</p>");
    //                           ^ Update the text directly when clicked
}

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.