egeloen / IvoryGoogleMapBundle

Google Map API v3 integration for your Symfony2 project.
https://github.com/egeloen/ivory-google-map
MIT License
217 stars 152 forks source link

Map does not load when on the same page as Autocomplete field #96

Closed ArturProd closed 8 years ago

ArturProd commented 10 years ago

Hello,

I am trying to use the autocomplete and google map on the same page and can't get it to work. I'm probably doing something wrong, but what?

The autocomplete field works good but the map does not display. If I manually call load_ivory_google_map from chrome javascript console, then the map loads well and works as expected.

When I look at the generated code, it seems that "load_ivory_google_map" is never called, because when loading the google api in "load_ivory_google_map_api", the callback is defined as "load_ivory_google_place" which never call in turn load_ivory_google_map ...

In my twig page:

            {{ google_map_css(map) }}
            {{ google_map_container(map) }}
            {{ google_map_js(map) }} 

           {{ form_widget(eventform.country) }}

in my formtype:

   $builder->add('country', 'places_autocomplete', array(
                    'mapped' => false,
                    // Javascript prefix variable
                    'prefix' => 'googleplace_country',
                    // Autocomplete types
                    'types'  => array(
                        AutocompleteType::CITIES,
                        // ...
                    ),

                    // TRUE if the autocomplete is loaded asynchonously else FALSE
                    'async' => true,

                    // Autocomplete language
                    'language' => 'en',
                ))

The way I build my map:

        $map = $this->get('ivory_google_map.map');
        $map->setLanguage($this->get('request')->getLocale());

my config file:

ivory_google_map:
    api: 
        libraries: [ "places" ]
    map:
        # You own map class
        #class: "My\Fucking\Map"

        # Your own map helper class
        #helper_class: "My\Fucking\MapHelper"

        # Prefix used for the generation of the map javascript variable
        prefix_javascript_variable: "map_"

        # HTML container ID used for the map container
        #html_container: "map_canvas"

        # If this flag is enabled, the map will load asynchronous
        async: true

        # If this flag is enabled, the map will autozoom on the overlays added
        auto_zoom: false

        # Center coordinate of the map
        # If the autozoom flag is enabled, the center is not used
        center:
            longitude: 0
            latitude: 0
            no_wrap: false

        # Zoom of the map
        # If the autozoom flag is enabled, the zoom is not used
        zoom: 3

        # Bound of the map
        # If the auto zoom flag is not enabled, the bound is not used
        # If the bound extends overlays, coordinates of the overlays extended are used instead of these coordinates
        # By default, there is no bound
#        bound:
#            south_west:
#                latitude: -2.1
#                longitude: -3.9
#                no_wrap: true
#            north_east:
#                latitude: 2.6
#                longitude: 1.4
#                no_wrap: true

        # Default map type
        # Available map type : hybrid, roadmap, satellite, terrain
        type: "roadmap"

        # Map width
        width: "200px"

        # Map height
        height: "200px"

        # Custom map options
        # By default, there is no map options
        map_options:
            disableDefaultUI: false
            disableDoubleClickZoom: false

        # Custom stylesheet options
        # By default, there is no stylesheet options except width & height
        stylesheet_options:
            border: "1px solid #000"
            background-color: "#fff"

        # google map Api language, default en
        language: en
ArturProd commented 10 years ago

Sorry the issue was sent twice!

egeloen commented 10 years ago

@ArturProd Thx for reporting this issue! IMO, the issue is related to the async mod of your map and autocomplete. It seems the ApiHelper can not handle this case... I need to investigate and look how it can be fixed as for now I don't really know :s

ciscorojo commented 10 years ago

HI , does anyone have found a solution ? tnx Cisco

egeloen commented 10 years ago

@ciscorojo IMO, I will not be able to fix it for the 1.x version mostly because I have absolutely not taking this feature into account when I have designed the library :s The fact, the api helper is coupled to the map/autocomplete feature does not allow me to fix it without changing everything about the api loading... Anyway, I'm currently working on the upcoming 2.x version since 2 weeks and this issue will be fixed in this version.

ciscorojo commented 10 years ago

opss....this a sad news for us....:) the 80% of our project is based on your great work!!!...we just discuss to attend or change our developmet..... tnx a lot egeloen...we hope to have your good news soon :) Cisco!!!

egeloen commented 10 years ago

If you want I have a workaround but I have no time to explain it tonight. I will explain it tomorrow.

ciscorojo commented 10 years ago

Ok....what you want when you want! :)

2014-06-19 22:42 GMT+02:00 Eric GELOEN notifications@github.com:

If you want I have a workaround but I have no time to explain it tonight. I will explain it tomorrow.

— Reply to this email directly or view it on GitHub https://github.com/egeloen/IvoryGoogleMapBundle/issues/96#issuecomment-46613969 .

egeloen commented 10 years ago

Sorry for the delay, I have a workaround but it depends how do you render the map and the autocomplete... Do you render first the map or the autocomplete?

ciscorojo commented 10 years ago

Hi Eric, I've an header who render the field for the search/autocomplete than in my Twig block body i have Map on twig called by {{ google_map_container(map) }} {{ google_map_js(map) }} Note . I've been used both google autocomplete and ivory autoc. but we have the same issue, after loaded {{ google_map_js(map) }} the autocomplete doesn't work! Tnx Cisco

2014-06-25 1:30 GMT+02:00 Eric GELOEN notifications@github.com:

Sorry for the delay, I have a workaround but it depends how do you render the map and the autocomplete... Do you render first the map or the autocomplete?

— Reply to this email directly or view it on GitHub https://github.com/egeloen/IvoryGoogleMapBundle/issues/96#issuecomment-47043839 .

jion commented 10 years ago

specifically, where is the error and what is the fix that solves it? While I wait for version 2, I like to manually resolve this to use the bundle in my application.

egeloen commented 10 years ago

The issue explanation

The issue is located in the ApiHelper which have the responsibility to render the google map api loader and so, loads the google api. When you configure your map and autocomplete as async, the generated map and autocomplete are wrapped in two js named functions in order to be executed further (async). Then, the name of these functions should be passed as callback to the loader in order to be executed once the api is really loaded in the browser. Unfortunately, when there are two callbacks to execute, the api helper is not able to execute both of them because it only accepts one and so, only the first one is executed... Fixing it is impossible in the current implementation because the MapHelper and AutocompleteHelper renders themself the api loading. So when you render the autocomplete first, the google library is loaded with the autocomplete helper js function as callback but additionally,the api helper marks the library as loaded because when you load two times the library in the page, the google library crashed. Then, when you will render the map, the js function is rendered and then, as the library is marked as already loaded, it does not load it anymore and so, does not execute the callback... In 2.0, the api will not be part of the map or autocomplete js rendering and so, will be aware there are multiple callbacks to execute. This is the only solution to the problem...

The workaround for 1.x

The solution depends in which order you render the map/autocomplete. If you render the map before the autocomplete, I would suggest you to create a MapExtensionHelper which triggers the autocomplete js function. Then, when the map callback will be executed it will trigger itself the autocomplete callback.

// Sets the places library as loaded library in your map
$map->setLibraries(array('places'));
use Ivory\GoogleMap\Helper\Extension\ExtensionHelperInterface;
use Ivory\GoogleMap\Map;

class AsyncAutocompleteExtensionHelper implements ExtensionHelperInterface
{
    pubic function renderAfter(Map $map)
    {
        return 'load_ivory_google_place();'.PHP_EOL;
    }
}

Then, just register this extension (I have not tested it but it should work).

If you render the autocomplete before the map, it is a little bit more complex as there is no extension for an autocomplete. The only solution is to do it in the template when you render the autocomplete. So, you need to override the places_autocomplete_widget form block and replace it with the following:

{% block places_autocomplete_widget %}
    {{ html | raw }}
    {{ javascripts | raw | slice(0, -11) ~ 'load_ivory_google_map();}</script>' }}
{% endblock %}
egeloen commented 8 years ago

Your issue has been fixes in #159 but will only be part of the 3.x version of the bundle.