gribnoysup / react-yandex-maps

Yandex Maps API bindings for React
MIT License
327 stars 114 forks source link

LoadingObjectManager. How to add the custom balloon? #271

Open aveselovalova opened 3 years ago

aveselovalova commented 3 years ago

I need to add the React component with buttons from the UI-kit library as a balloon. Should I implement the balloonContentLayout option or smth else?

const initializeMap = () => {
    const objectManager = new ymaps.LoadingObjectManager(autoApiUrlForLoading, objectManagerProps);
    objectManager.clusters.options.set({...});
    objectManager.options.set('geoObjectOpenBalloonOnClick', false);
    objectManager.objects.options.set({...});

    objectManager.objects.events.add(['click'], (event: any) => {
        const objectId = event.get('objectId');
        const data = objectManager.objects.getById(objectId); // receive data for the balloon

        objectManager.objects.options.set({
            balloonContentLayout: makeLayout(ymaps.templateLayoutFactory), // ???
        });

        objectManager.objects.balloon.open(objectId);
    });
    ...
}

....

return (
    <div className={styles.map} ref={containerRef}>
        <YMaps query={{ load: 'package.full' }}>
            <YandexMap
                {...MAP_SETTINGS}
                state={mapState}
                onLoad={(maps: YMapsApi): void => {
                    if (maps && !ymaps) {
                        setYmaps(maps);
                    }
                }}
                instanceRef={ref => {
                    mapRef.current = ref;
                }}
            />
        </YMaps>
    </div>
);
mmarkelov commented 3 years ago

@aveselovalova there are some issues that can help you: https://github.com/gribnoysup/react-yandex-maps/issues/150, https://github.com/gribnoysup/react-yandex-maps/issues/130, https://github.com/gribnoysup/react-yandex-maps/issues/27

Unfortunately ymaps.templateLayoutFactory does not support react components. Only html string template. So if you don't have any logic inside balloon it will be easier to use just html strings. Otherwise you will need to implement some difficult logic. Also I made some research on how it can be done, so you can checkout this, but it was quite old solution.

aveselovalova commented 3 years ago

@mmarkelov Thanks for the answer. Are you going to implement React components support for ymaps.templateLayoutFactory in the future?

I implement the template as a html string and completely update the click event if some props have changed, like this...

useEffect(() => {
    objectManager.objects.events.remove(['click']);
    objectManager.objects.events.add(['click'], event => {
        const objectId = event.get('objectId');
        const data = objectManager.objects.getById(objectId);
        objectManager.objects.options.set({
            balloonContentLayout: makeLayout(ymaps.templateLayoutFactory, data),
        });
        objectManager.objects.balloon.open(objectId);
    });
}, [id, preventSelection]);
mmarkelov commented 3 years ago

Are you going to implement React components support for ymaps.templateLayoutFactory in the future?

@aveselovalova IDK. I just tried some integration about 1.5 years ago. And I was not sure that I was able to handle with possible cases. To my mind this is something that we should to have, but it's maybe something challenging to do.