erdem / django-map-widgets

Highly customizable, intuitive, and user-friendly map widgets for GeoDjango applications.
MIT License
449 stars 119 forks source link

Leaflet widget not refreshing when data is changed #154

Closed ShmuelTreiger closed 3 months ago

ShmuelTreiger commented 3 months ago

Hi! (Sorry for opening so many issues, just tring to get my project working.)

I have some javascript

        function updateMapPointBasedOnAddress() {
            const address = document.getElementById('{{ form.address.id_for_label }}').value;
            jQuery.ajax({
                // calls my view which returns a properly formatted point
                url: '{% url "update_map_point_based_on_address" %}',
                method: 'GET',
                data: {address: address},
                success: function (data) {
                    document.getElementById('{{ form.address_point.id_for_label }}').value = data.address_point;
                    // example of other field
                   document.getElementById('{{ form.description.id_for_label }}').value = data.address_point; 
                },
                error: function (error) {
                    console.error('Error:', error);
                }
            });
        }

This javascript makes a call to my api to turn my address into a point and then updates my address_point based on the return value. However, this value doesn't reflect on the map displayed on the page. (When I save the form, the change is saved in the database.) Is there a way to reflect this value change in the active html? When I save it to a different form field (just a text field) it shows up right away.

Not sure if this is a bug or WAI, but thought I'd raise it see what you have to say. Thanks!

erdem commented 3 months ago

The widget won't update if you only change the django form input; you need to trigger the JS class events too. This is actually a nice feature request. It would be better if we managed map updates via a JS event when a marker needs to be added to the map. I will consider implementing this feature in the next major release.

However, there is a solution to handle your case. As I mentioned in my previous reply, you need to call widget class functions through the element's bound data object.

Here is my sketchy implementation to update a field(location) on my django form class. You can apply the same implementation for your ajax call.

<script type="text/javascript">
    (function ($) {
        const widgetClassObj = $("#location-map-elem").data("mwClassObj")
        setTimeout(function () {
            // widgetClass.addMarkerToMap(lat, lng)
            widgetClassObj.addMarkerToMap(51.6575243834443, -0.1548867463910279)  // add marker to map
            widgetClassObj.updateDjangoInput() // update django input
            widgetClassObj.fitBoundMarker() // fix center position for the marker

            setTimeout(function () {
                // you can reset the map with `widgetClassObj.resetMap()`
                widgetClassObj.resetMap()
            }, 5000)

        }, 3000)
    })(jQuery)
</script>