Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MglGeoJsonSource features do not maintain 'id' attribute #128

Open
whilei opened this issue Jan 27, 2025 · 0 comments
Open

MglGeoJsonSource features do not maintain 'id' attribute #128

whilei opened this issue Jan 27, 2025 · 0 comments

Comments

@whilei
Copy link

whilei commented Jan 27, 2025

I'm using code similar to the following, but in attempting to build a hoverState composable -- which relies on map.setFeatureState({id: X, ...}) and map.removeFeatureState({id: X, ...}), have found that the feature id attribute for the features is not available in GeoJSON source/layers. I have not found this issue with Vector Tile sources.

Errors look like this:

Error: The feature id parameter must be provided.
    setFeatureState style.ts:1251
    setFeatureState map.ts:2878
    useMapHover mapHover.js:30
    callWithErrorHandling runtime-core.esm-bundler.js:199
    callWithAsyncErrorHandling runtime-core.esm-bundler.js:206

Error: A feature id is required to remove its specific state property.
    removeFeatureState style.ts:1276
    removeFeatureState map.ts:2929
    useMapHover mapHover.js:16
    callWithErrorHandling runtime-core.esm-bundler.js:199
    callWithAsyncErrorHandling runtime-core.esm-bundler.js:206
    call runtime-core.esm-bundler.js:6193

As a workaround, I'm able to use :generate-id="true" on the mgl-geo-json-source, like below, but this obviously not ideal (since features can't be referenced later by their actual id).

            <mgl-geo-json-source v-for="(fc, index) in featureCollections"
                                 :key="fc.id || index"
                                 :source-id="`${fc.id || 'fc-'+index}`"
                                 :data="fc"
                                 :generate-id="true"
            >

Similar experiments with :promote-id="'id'" have likewise failed.


General code context/snippets:
(feature.source is currently manually assigned and existing, and feature.sourceLayer is intentionally null, required for xFeatureState() calls on GeoJSON sources)

            <mgl-geo-json-source v-for="(fc, index) in featureCollections"
                                 :key="fc.id || index"
                                 :source-id="`${fc.id || 'fc-'+index}`"
                                 :data="fc"
            >
                <template v-if="fc.features?.length > 0">
                    <mgl-circle-layer v-if="anyGeo(fc, 'Point')"
                                      :layer-id="getLayerId(fc, 'Point', index)"
                                      :paint="getPaint(fc.resource, fc.tilestat, firstFeatureWhereGeo(fc, 'Point'))"
                                      @mouseenter="mouseEvent($event)"
                                      @mouseover="mouseEvent($event)"
                                      @mousemove="mouseEvent($event)"
                                      @mouseleave="mouseEvent($event)"
                                      @click="mouseEvent($event)"
                    />
                    <mgl-line-layer v-if="anyGeo(fc, 'LineString')"
                                    :layer-id="getLayerId(fc, 'LineString', index)"
                                    :paint="getPaint(fc.resource, fc.tilestat, firstFeatureWhereGeo(fc, 'LineString'))"
                                    @mouseenter="mouseEvent($event)"
                                    @mouseover="mouseEvent($event)"
                                    @mousemove="mouseEvent($event)"
                                    @mouseleave="mouseEvent($event)"
                                    @click="mouseEvent($event)"
                    />
...
    const hoveredFeatures = ref([]);

    watch(
        hoveredFeatures, (newVal, oldVal) => {
        for (const feat of oldVal) {
            // console.log('useMapHover.watch#remove.oldVal', feat);
            if (!_map.map.getSource(feat.source)) {
                continue;
            };

            try {
                _map.map.removeFeatureState({
                    source: feat.source,
                    sourceLayer: feat.sourceLayer,
                    id: feat.id,
                }, 'hover');
            } catch (error) {
                // console.error('useMapHover.watch#remove.oldVal.error', error);
            }

        }
        for (const feat of newVal) {
            // console.log("useMapHover.watch#add.newVal", feat);
            if (!_map.map.getSource(feat.source)) continue;
            try {
                _map.map.setFeatureState({
                    source: feat.source,
                    sourceLayer: feat.sourceLayer,
                    id: feat.id,
                }, { hover: true });
            } catch(error) {
                // console.error('useMapHover.watch#add.newVal.error', error);
            }

        }
...

    function onHoverMouseEvent(e) {
        switch (e.type) {
            case 'mousemove': // 'mouseenter',
                let features = e.features;
                setHoveredFeatures(features);
                break;
            case 'mouseleave':
                setHoveredFeatures([]);
                break;
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant