3

I'm using SmartMap in a front end entry form and trying to set the position of a marker as the user enters their address.

I can get the lat/lon lookup working but I'm stumped with the marker itself.

Here's my Javascript that's doing the lookup and filling in the lat/lon

$.post('/actions/smartMap/lookup', data, function(response) {
    if(response.status = 'OK'){
        // get lat/lng and populate hidden fields
        $('.js-address-lat').val(response.results[0].geometry.location.lat);
        $('.js-address-lng').val(response.results[0].geometry.location.lng);

        // update map (add marker)
        smartMap.map['smartmap-mapcanvas-1'].setOptions({styles: styles});

        var lat = parseFloat(response.results[0].geometry.location.lat);
        var lng = parseFloat(response.results[0].geometry.location.lng);
        var newLatLng = new google.maps.LatLng(lat, lng);

        smartMap.marker['smartmap-mapcanvas-1.{{ property.id }}.location'].setPosition(newLatLng)

        smartMap.refreshMap(smartmap-mapcanvas-1);

    } else {
        alert('No address could be found');
    }
});

The docs say to reference the marker as

smartMap.marker['<MAP ID>.<ELEMENT ID>.<FIELD HANDLE>']

With the <ELEMENT ID> being the ID of the marker's parent element. But what would be? Is that the ID of the entry? I'm trying that but it just seems to lock the browser up and the fields don't save.

  • Do you just want to set the position temporarily for this request or do you want to save it? Usually you need to resave the element - not sure if smartmap includes a custom logic to update the map field only but your way to go is usually change the field value and resave the element – Robin Schambach Jul 29 '18 at 11:57
  • Seems that the above works fine other than the need to recentre the map. I had another issue (styles wasn't defined) which made it look like it wasn't working. – foamcow Jul 29 '18 at 12:03
  • Okay, would you mind answering the question with your solution in case someone has the same issue? – Robin Schambach Jul 29 '18 at 12:04
  • Yes Robin. The idea is to update the position permanently. I'm saving the new lat/lon in a hidden field. This is just for some feedback to the user. – foamcow Jul 29 '18 at 12:06
  • Will do. Just going to fix the rest of it so I can post a complete answer. – foamcow Jul 29 '18 at 12:06
4

Turns out my code was pretty much working but there was another issue in there that was stopping the map marker updating. I've since resolved it. The original form is huge so here's a cut down snippet of the part that does the marker update in case anyone needs it. This cut-down version isn't tested but should be good.

Incidentally, the "parent element ID" to which I referred is the id of the entry in which your map resides.

Basic location update form (my entry is 'property')

<form id="property-edit__form" method="post" accept-charset="UTF-8" enctype="multipart/form-data">
    {{ getCsrfInput() }}    
    {% if property is defined %}
        <input type="hidden" name="action" value="entries/saveEntry">
        <input type="hidden" name="entryId" value="{{ property.id }}">
        <input type="hidden" name="sectionId" value="{{ property.sectionId }}">
        <input type="hidden" name="enabled" value="{{ property.enabled }}">
    {% else %}
        <input type="hidden" name="action" value="entries/saveEntry">
        <input type="hidden" name="sectionId" value="3">
        <input type="hidden" name="enabled" value="0">
        <input type="hidden" name="redirect" value="me/property/saved">
    {% endif %}

    <div class="property-edit__map-fields">
        <label>
            Street Address
            <input class="js-address-part" type="text" name="fields[location][street1]" value="{{property.location.street1 ?? ''}}">
        </label>

        <label>
            City
            <input class="js-address-part" type="text" name="fields[location][city]" value="{{property.location.city ?? ''}}">
        </label>

        <label>
            County
            <input class="js-address-part" type="text" name="fields[location][state]" value="{{property.location.state ?? ''}}">
        </label>

        <label>
            Post Code
            <input class="js-address-part" type="text" name="fields[location][zip]" value="{{property.location.zip ?? ''}}">
        </label>

        <label>
            Country
            <input class="js-address-part" type="text" name="fields[location][country]" value="{{property.location.country ?? ''}}">
        </label>


        <input class="js-address-lat" type="hidden" name="fields[location][lat]" value="{{property.location.lat ?? ''}}">

        <input class="js-address-lng" type="hidden" name="fields[location][lng]" value="{{property.location.lng ?? ''}}">


        <div><button class="js-address-lookup">Lookup address</button></div>

    </div>


    <div class="property-edit__map">
        {% if property is defined and property.location.hasCoords %}

            {% set options = {
                height: 300,
                width: '100%',
                zoom: 11,
                markerOptions: {
                    icon: '/images/map-marker.png'
                    },
                } 
            %}
        {% else %}
            {% set options = {
                height: 300,
                width: '100%',
                zoom: 4,
                center: { 'lat': 51.499998 , 'lng': -0.1166662},
                markerOptions: {
                    icon: '/images/map-marker.png'
                    },
                } 
            %}
        {% endif %}

        {% if property is defined %}    
            {{ craft.smartMap.map(property.location, options) }}
        {% endif %}
    </div>


    <input type="submit" value="Save">  
</form>

And some Javascript to do the business (using jQuery here).

<script>

    $('body').on('click', '.js-address-lookup',  function (event) {
        event.preventDefault;

        var target = '';
        $('.js-address-part').each(function(){
            target += $(this).val() + ',';
        });
        var data   = {target: target};

        var csrfTokenName  = "{{ craft.config.get('csrfTokenName') }}";
        var csrfTokenValue = "{{ craft.request.getCsrfToken }}";

        data[csrfTokenName] = csrfTokenValue; // Append CSRF Token to outgoing data

        $.post('/actions/smartMap/lookup', data, function(response) {
            if(response.status = 'OK'){
                // get lat/lng and populate hidden fields
                $('.js-address-lat').val(response.results[0].geometry.location.lat);
                $('.js-address-lng').val(response.results[0].geometry.location.lng);

                // update map (add marker)
                var lat = parseFloat(response.results[0].geometry.location.lat);
                var lng = parseFloat(response.results[0].geometry.location.lng);
                var newLatLng = new google.maps.LatLng(lat, lng);

                {% if property is defined %}
                    smartMap.marker['smartmap-mapcanvas-1.{{ property.id }}.location'].setPosition(newLatLng)
                {% endif %}

                //smartMap.map['smartmap-mapcanvas-1'].setOptions({styles: styles});

                smartMap.map['smartmap-mapcanvas-1'].panTo(newLatLng);
                smartMap.refreshMap(smartmap-mapcanvas-1);

            } else {
                alert('No address could be found');
            }
        });
    });

</script>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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