putyourlightson / craft-sprig

A reactive Twig component framework for Craft CMS.
https://putyourlightson.com/plugins/sprig
MIT License
124 stars 9 forks source link

Sprig filter with a Google Map #107

Closed ConversioniaDev closed 3 years ago

ConversioniaDev commented 3 years ago

Question

I have a Google Map within a Sprig component that loads fine until I apply a filter. The map still loads but it covers the browser window and doesn't show the updated results. Am I missing something on the filter to allow it to work with the map? I'm using the beta version of SmartMap which appears to be working fine until a Sprig filter is applied.

Here is a stripped down version of the code showing a couple of filters and the map.

<div s-replace="#jobListings">

    <div id="pageTitle" class="d-flex align-items-end px-2 py-3 mb-3 text-white bg-purple rounded shadow-sm">
        <div class="col px-2">
            <small><i class="bi bi-funnel"></i> DRIVER TYPE</small>
            <select sprig id="driverType" name="driverType" class="form-select" aria-label="-Select-">
                {% for option in driverType.options %}
                    {% set selected = entry is defined
                        ? entry.driverType.value == option.value
                        : option.default %}
                    {% set driverType = option.value %}
                    <option value="{{ driverType }}"{% if selected %}selected{% endif %}>
                        {{ option.label }}
                    </option>
                {% endfor %}
            </select>
        </div>
        <div class="col px-2">
            <small><i class="bi bi-funnel"></i> TRUCK TYPE</small>
            <select sprig id="truckType" name="truckType" class="form-select" aria-label="-Select-">
                {% for option in truckType.options %}
                    {% set selected = entry is defined
                        ? entry.truckType.value == option.value
                        : option.default %}
                    {% set truckType = option.value %}
                    <option value="{{ truckType }}"{% if selected %}selected{% endif %}>
                        {{ option.label }}
                    </option>
                {% endfor %}
            </select>
        </div>
    </div>

    <div id="jobListings">
        <div class="col-sm-12 my-4">
            {# Get all locations #}
            {% set locations = craft.entries.section('jobs').all() %}

            {% set options = {
                id: 'my-map',
                height: 300,
                zoom: 6,
                draggable: false,
                markerOptions: {
                    icon: 'https://maps.google.com/mapfiles/ms/icons/green-dot.png'
                },
                infoWindowOptions: {
                    maxWidth: 200
                }
            } %}
            {% set map = googleMaps.map(locations, options) %}
            {{ map.tag() }}

        </div>
    </div>
</div>

{{ sprig.script }}

<script>
    htmx.on('htmx:afterSwap', function(event) {
        googleMaps.init('my-map');
    });
</script>

Additional context

Add any other context or screenshots about the support request here.

bencroker commented 3 years ago

First thing I notice is that the following code should exist in the parent template, not in the component itself:

{{ sprig.script }}

<script>
    htmx.on('htmx:afterSwap', function(event) {
        googleMaps.init('my-map');
    });
</script>

Secondly, if using the new SmartMap beta then apparently there is a solution, see https://github.com/putyourlightson/craft-sprig/issues/78#issuecomment-777670131

ConversioniaDev commented 3 years ago

It's in the parent template. I just included it to show what's in the template. I have it in the footer with my other JS calls.

bencroker commented 3 years ago

In that case, please contact @lindseydiloreto for the solution.

ConversioniaDev commented 3 years ago

Thanks, Ben. I'm guessing you didn't see anything off in the code example provided related to Sprig?

bencroker commented 3 years ago

Not besides what I already pointed out.

lindseydiloreto commented 3 years ago

@bencroker Fwiw, @ConversioniaDev and I have already chatted about this issue. It looks like Google Maps isn't to blame, and perhaps neither is Sprig... the solution is probably somewhere in between.

@ConversioniaDev Hit me up via Discord (again), we can try to sort it out one more time. We'll open up a 3-way conversation with @bencroker if we need to.

bencroker commented 3 years ago

Am happy to help out, but it seems that this in relation to code that is not yet public?

lindseydiloreto commented 3 years ago

It'll be public in a few days. Not sure that matters though, I can provide you with a copy of the plugin.

ConversioniaDev commented 3 years ago

Thanks, @lindseydiloreto and @bencroker.

@lindseydiloreto, I'll ping you on Discord.

lindseydiloreto commented 3 years ago

Got it, here is the final solution...

<script>
    htmx.on('htmx:afterSwap', function(event) {
        setTimeout(function(){
            googleMaps.init('my-map');
        }, 200);
    });
</script>

The Google API was trying to refresh the map before HTMX had finished rendering the new DOM. So it's necessary to delay the map refresh until we can be confident that HTMX is finished.

This will prevent the map from going outside of its container when reloaded by Sprig.

bencroker commented 3 years ago

Nice!! Using the htmx:afterSettle event might work without even requiring the timeout, since it waits 100ms after htmx:afterSwap before firing, by default.

lindseydiloreto commented 3 years ago

Good tip, thanks @bencroker! 🍺

ConversioniaDev commented 3 years ago

Thanks, @bencroker! The htmx:afterSettle worked without issue.

lindseydiloreto commented 2 years ago

Good news, we've officially documented the process for using Sprig with Google Maps! 👏

Any other questions, feel free to ping to Double Secret Agency!