Mapbox-gl-js: Unable use the id operator in an Expression

Created on 21 Apr 2018  ·  4Comments  ·  Source: mapbox/mapbox-gl-js

Expression operator ['id'] doesn't seem to match anything

mapbox-gl-js version: 0.44.2

Steps to Trigger Behavior

  1. Create a geojson data source and attach it to a layer. For each feature in the data source, set an id, so that it doesn't get assign a 32-digit hex string id by mapbox
  2. Try and use the id in a case expression to change the colour
    3.

Expected Behavior

It should be possible to change a property such as fill-color based on the id.
For example: ['case', ['==', 'id', 'some-id'], 'red', 'blue'] I would expect to make all the things blue except for the single feature which has id some-id

Actual Behavior

For example: ['case', ['==', 'id', 'some-id'], 'red', 'blue'] sets everything blue, ignoring the id

I did a little digging, and found the code for Case in mapbox-gl-js source, so I patched the dist with a console.log and discovered that in a function EvaluationContext.id() which appears to retrieve the id, by safely returning this.feature.id , when I printed this.feature there was no id property present in the browser object log however there was properties, which appeared to have all the features properties, and a field called _feature which did have the id...

Edit

There is a typo above (preserved for context) the filter should wrap id in an array bracket, i.e. ['case', ['==', ['id'], 'some-id'], 'red', 'blue']

Most helpful comment

So I played with the jsbin and it seems that the id must be a number not a string. That explains that

All 4 comments

Per https://www.mapbox.com/mapbox-gl-js/style-spec#expressions-id, you need ['id'] to get the feature id. 'id' will just get the property named id.

map.addLayer({
        "id": "points",
        "type": "symbol",
        "source": {
            "type": "geojson",
            "data": {
                "type": "FeatureCollection",
                "features": [{
                    "type": "Feature",
                    "id": 1,
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-77.03238901390978, 38.913188059745586]
                    },
                    "properties": {
                        "title": "A",
                        "icon": "monument",
                        "id": "A"
                    }
                }, {
                    "type": "Feature",
                    "id": 2,
                    "geometry": {
                        "type": "Point",
                        "coordinates": [-122.414, 37.776]
                    },
                    "properties": {
                        "title": "B",
                        "icon": "harbor",
                        "id": "B"
                    }
                }]
            }
        },
        "layout": {
            "icon-image": "{icon}-15",
            "text-field": "{title}",
            "text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
            "text-offset": [0, 0.6],
            "text-anchor": "top"
        },
        "filter": ["==", ["id"], 2] // or  ["==", "id", "B"]
    });

compare http://jsbin.com/tifupud/2/edit?html,output and http://jsbin.com/tifupud/3/edit?html,output

PS. It seems when using filter in querySourceFeatures it still uses https://www.mapbox.com/mapbox-gl-js/style-spec/#other-filter which uses '$id' for id and 'id' for the property named 'id'.

hmm

Thanks for this. It seems I made a typo in my problem report, sorry.

I'm definitely trying not to use the deprecated syntax.

in my code I have definitely set the filter as you say it should be:
this.map.setFilter('layerId', ['==', ['id'], 'Hello-4'])
and using console.log(map.getStyle()) I see

layers: Array
...
{id: "layerId", type: "line", source: "sourceId", filter: ["==", ["id"], "Hello-4"], paint: Object}
...
sources: 
sourceId:
data Object
features: [Object, Object, ...]
...
{type: "Feature", id: "Hello-4", properties: Object, geometry: Object}
...

I'll triple check again, and compare it against the jsbin, but it seems to be right, apart from not otherwise working. Still, I did make one typo already...

So I played with the jsbin and it seems that the id must be a number not a string. That explains that

So I played with the jsbin and it seems that the id must be a number not a string. That explains that

There's a bit of discussion about that at https://github.com/mapbox/mapbox-gl-js/issues/2716

Was this page helpful?
0 / 5 - 0 ratings