dash-leaflet icon indicating copy to clipboard operation
dash-leaflet copied to clipboard

Vector tile layer

Open emilhe opened this issue 1 year ago • 12 comments

The PR introduces a VectorTileLayer component, based on this library, which enables rendering of (protobuf) vector tiles.

import dash_leaflet as dl
from dash import Dash
from dash_extensions.javascript import assign

eventHandlers = dict(click=assign("function(e, ctx){console.log(e); console.log(ctx);}"))

app = Dash()
app.layout = dl.Map(
    [
        dl.TileLayer(),
        dl.VectorTileLayer(url="https://openinframap.org/tiles/{z}/{x}/{y}.pbf", maxDetailZoom=6, style={}, eventHandlers=eventHandlers),
    ],
    center=[56, 10],
    zoom=8,
    style={"height": "50vh"},
)

if __name__ == "__main__":
    app.run_server(debug=True)

emilhe avatar Oct 07 '24 19:10 emilhe

@Eric-UW-CRL thanks for the feedback! There is nothing wrong with your code - i just didn't get to event handlers in the first take. If you bump to the next rc version,

pip install dash-leaflet==1.0.17rc2

your code should work. For reference, I have updated the example in the PR post to use event handlers. Note, I have not added any default event handlers yet (i.e. you don't have e.g. an n_clicks proper like many other components).

emilhe avatar Oct 14 '24 17:10 emilhe

@emilhe I see! I gave the update a try, and my event handler now works on clicks.

I was looking at the default event handlers for the GeoJSON components, and maybe it makes sense to add the same defaults for this? I imagine users would primarily want to click on the features or mouse over them to get the properties. My simple attempt using a custom event handler was as follows. This gives me enough control however to get the data from the features that I need.

eventHandlers = dict(
    click=assign(
        "function(e, ctx){ctx.setProps({clickData: e.layer.feature.properties})}"
    )
)

emacollins avatar Oct 15 '24 23:10 emacollins

This would be a super welcome addition to this awesome package! :)

I have a use case where the tile layer also accepts query parameters (i.e., passed in the url in the form "?param1=value1"). Is there any way that we can pass the values of these query parameters dynamically via a dash callback (e.g., depending on selected user input)? Is this what fetchOptions is meant for? (I don't seem to get it to work ... 😢 )

kepiej avatar Nov 07 '24 07:11 kepiej

This would be a super welcome addition to this awesome package! :)

I have a use case where the tile layer also accepts query parameters (i.e., passed in the url in the form "?param1=value1"). Is there any way that we can pass the values of these query parameters dynamically via a dash callback (e.g., depending on selected user input)?

Is this what fetchOptions is meant for? (I don't seem to get it to work ... 😢 )

Did you try just passing the URL with parameters included?

FetchOptions are options passed to the request itself (method, headers, etc.)

emilhe avatar Nov 07 '24 10:11 emilhe

This would be a super welcome addition to this awesome package! :) I have a use case where the tile layer also accepts query parameters (i.e., passed in the url in the form "?param1=value1"). Is there any way that we can pass the values of these query parameters dynamically via a dash callback (e.g., depending on selected user input)? Is this what fetchOptions is meant for? (I don't seem to get it to work ... 😢 )

Did you try just passing the URL with parameters included?

Yes, that works but is not exactly what I'm looking for: I would like to be able to change the value of the query parameter dynamically (e.g., through a dash callback) when a user makes a different selection in a dropdown box. So the value in "?param1=value" would be modified by user interaction.

kepiej avatar Nov 07 '24 10:11 kepiej

In that case, I guess if the URL was made dynamic (i.e that it can be changed by a callback), that would support your use case also?

emilhe avatar Nov 07 '24 10:11 emilhe

In that case, I guess if the URL was made dynamic (i.e that it can be changed by a callback), that would support your use case also?

Yes, absolutely! 👍 I tried modifying it with a callback but that doesn't work currently. Hence my question here. :)

kepiej avatar Nov 07 '24 11:11 kepiej

This feature would also be super helpful for me! 😸

MonSeco avatar Dec 03 '24 12:12 MonSeco

In that case, I guess if the URL was made dynamic (i.e that it can be changed by a callback), that would support your use case also?

@emilhe Do you have any idea when this could be included? This functionality would be really convenient for my own project instead of other workarounds. :)

kepiej avatar Jan 31 '25 08:01 kepiej

This feature would also be super helpful for me!

frederikbylvito avatar Jan 31 '25 10:01 frederikbylvito

In that case, I guess if the URL was made dynamic (i.e that it can be changed by a callback), that would support your use case also?

@emilhe : I was able to find a workaround that doesn't need a dynamic URL so the current Vector tile layer functionality is sufficient for my use case. :)

kepiej avatar May 12 '25 10:05 kepiej

@emilhe Hi emilhe,

Thank you for your hard work on this VectorTileLayer component! It's a feature I've been really looking forward to.

I've noticed that this PR seems to be blocked by a failed test in the GitHub Actions. I ran the tests on my local environment. It seems that if the assertion assert dash_duo.find_element("#log").text == "null" is changed to assert dash_duo.find_element("#log").text == "" in test_components.py, the test passes.

I also did some digging and it looks like the output of json.dumps(e) in stubs.py is returning an empty string "" instead of "null". I wasn't able to fully pinpoint the root cause, but it feels like some dependency update or a change in the JSONEncoder's behavior might be the reason.

I hope this information is helpful in getting this PR merged. Thanks again for all your efforts!

akit-jwits avatar Aug 17 '25 14:08 akit-jwits