diff --git a/package-lock.json b/package-lock.json index 7676a4b..6b66f07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dash-leaflet", - "version": "1.0.15", + "version": "1.0.17rc2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dash-leaflet", - "version": "1.0.15", + "version": "1.0.17rc2.5", "license": "MIT", "dependencies": { "@mapbox/vector-tile": "^2.0.3", diff --git a/package.json b/package.json index 9c8e5f2..cfa1f62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dash-leaflet", - "version": "1.0.17rc2", + "version": "1.0.17rc2.5", "description": "Dash Leaflet is a light wrapper around React-Leaflet. The syntax is similar to other Dash components, with naming conventions following the React-Leaflet API.", "main": "index.ts", "repository": { diff --git a/src/ts/react-leaflet/VectorTileLayer.ts b/src/ts/react-leaflet/VectorTileLayer.ts index 76e808c..12ed288 100644 --- a/src/ts/react-leaflet/VectorTileLayer.ts +++ b/src/ts/react-leaflet/VectorTileLayer.ts @@ -9,7 +9,7 @@ import { import { default as leafletVectorTileLayer } from 'leaflet-vector-tile-layer' import { DashFunction, Modify, resolveProps, TileLayerProps } from "../props"; import { omit, pick } from "../utils"; -import { GridLayer, TileLayer } from 'leaflet'; +import { GridLayer, TileLayer, TileLayerOptions } from 'leaflet'; export type VectorTileLayerOptions = { /** @@ -72,6 +72,12 @@ export type VectorTileLayerOptions = { */ vectorTileLayerStyles?: object; // default undefined + /** + * Passing a Python dictionary, this dictionary will be turned into + * a URLSearchParams JavaScript object, which will correspond to {q} in the following url + * https://xyz/collections/schema.table/tiles/WebMercatorQuad/{z}/{x}/{y}?{q} + */ + query?: object; } export type VectorTileLayerProps = Modify( + function createTileLayer({ url, ...options }, context) { + const q = new URLSearchParams({}); + + if (options.query != null) { + for (const [key, value] of Object.entries(options.query)) { + q.append(key,value); + } + } + const resolvedOptions = resolveProps(options, _funcOptions, context); - const layer = leafletVectorTileLayer(url, withPane(resolvedOptions, context)) - return createElementObject(layer, context) + const layer = leafletVectorTileLayer(url, Object.assign({},withPane(resolvedOptions, context), {q})); + return createElementObject(layer, context); }, function updateTileLayer(layer, props, prevProps) { - updateGridLayer(layer, props, prevProps) - const { url } = props + updateGridLayer(layer, props, prevProps); + const { query, style } = props; // TODO: Double check property stuff here - if (url != null && url !== prevProps.url) { - layer.setUrl(url) + if (query != null && JSON.stringify(query) != JSON.stringify(prevProps.query)) { + + const new_query_keys = Object.keys(query); + const q = (layer.options as ExtendedTileLayerOptions).q; + const _oldKeyToRemove = []; + // loop through the old query + q.forEach((value, key) => { + if (new_query_keys.includes(key)) { + if (query[key] !== value) { + q.set(key, query[key]); + } + } + else { + _oldKeyToRemove.push(key); + } + }); + + for (let _key of _oldKeyToRemove) { + if (_key != null) { + q.delete(_key); + } + } + + // loop through new query + for (const [key, value] of Object.entries(query)) { + if (!q.has(key)) { + q.append(key,value); + } + } + + layer.redraw(); + } + + if (style != null && checkStrictEqualStyle(style, prevProps.style)==false) { + //console.log("Update style"); + //console.log(prevProps.style); + //console.log(style); + layer.setStyle(style); + // In most cases setStyle does not require calling layer redraw method + // as the layer is updated automatically, but in some situations (such as + // applying a filter to get a subset of features shown -> zoom out or in + // -> remove the filter), the layer will not update automatically + + const zoomWhenStyleChanged = (layer.options as ExtendedTileLayerOptions).zoomWhenStyleChanged; + if (zoomWhenStyleChanged == null) { + (layer.options as ExtendedTileLayerOptions).zoomWhenStyleChanged = layer["_tileZoom"]; + //console.log(`First time set zoomWhenStyleChanged to ${layer["_tileZoom"]}`); + } + else if (zoomWhenStyleChanged !== layer["_tileZoom"]) { + layer.redraw(); + //console.log(`Redraw: ${zoomWhenStyleChanged} changed to ${layer["_tileZoom"]}`); + (layer.options as ExtendedTileLayerOptions).zoomWhenStyleChanged = layer["_tileZoom"]; + } } }, )