koaning / fh-altair

Makes it easy to use altair from FastHTML
MIT License
21 stars 1 forks source link

adding interactivity to altair plots #5

Closed gregory1506 closed 2 months ago

gregory1506 commented 2 months ago

hi there. i'm trying to add interactivity to the altair plot. below is a basic prototype that just creates a map and a Card.

from fasthtml.common import *
from shadcn import *
from fh_altair import altair2fasthml, altair_headers
import altair as alt

app, rt = fast_app(
    pico=False,
    hdrs=(ShadHead(lucid=False),altair_headers)
)

def generate_altair_chart():
    from vega_datasets import data
    counties = alt.topo_feature(data.us_10m.url, 'counties')
    source = data.unemployment.url
    slider = alt.binding_range(min=0, max=1, step=0.05, name='opacity:')
    chart = alt.Chart(counties).mark_geoshape().encode(
        color='rate:Q'
        ).transform_lookup(
            lookup='id',
            from_=alt.LookupData(source, 'id', ['rate'])
        ).project(
            type='albersUsa'
        ).properties(
            width=500,
            height=300
        )
    return altair2fasthml(chart)

@app.get("/")
def home():
    return Div(
        Div(
            generate_altair_chart(),
            cls="col-xs-12"
        ),
        Div(
            Card(
                Input(type="text", placeholder="Enter some text..."),
                title="Create a post",
                description="Enter your post title below.",
                footer=Div(
                    Button("Cancel", variant="outline"),
                    Button("Submit"),
                    cls="flex w-full justify-end gap-2",
                ),
                cls="w-[80%]",
            ),
        ),
        cls="row", style="color: #fff;"
    )

i would like to use the syntax of return altair2fasthml(chart + slider) to get interactivity but it does not seem to work. is there a way to do this?

image

koaning commented 2 months ago

Just to confirm before I dive in, are you able to confirm that the interactivity does work from within a Jupyter notebook? I am mainly asking to rule out if there is something with your chart definition.

gregory1506 commented 2 months ago

yes. But I can get the interactivity working if i change to this code.

slider = alt.binding_range(min=0, max=1, step=0.05, name='opacity:')
op_var = alt.param(value=0.1, bind=slider)
chart = alt.Chart(counties).mark_geoshape(opacity=op_var).encode(
    color='rate:Q'
    ).transform_lookup(
        lookup='id',
        from_=alt.LookupData(source, 'id', ['rate'])
    ).project(
        type='albersUsa'
    ).properties(
        width=500,
        height=300
    ).add_params(
        op_var
    )

so perhaps the syntax of chart + slider is not possible? image

koaning commented 2 months ago

Try this code:

import altair as alt

from vega_datasets import data

counties = alt.topo_feature(data.us_10m.url, 'counties')
source = data.unemployment.url
slider = alt.binding_range(min=0, max=1, step=0.05, name='opacity:')
op_var = alt.param(value=0.1, bind=slider)

chart = alt.Chart(counties).mark_geoshape(opacity=op_var).encode(
    color='rate:Q'
    ).transform_lookup(
        lookup='id',
        from_=alt.LookupData(source, 'id', ['rate'])
    ).project(
        type='albersUsa'
    ).properties(
        width=500,
        height=300
    ).add_params(
        op_var
    )

chart

My guess is that you perhaps miscopied something from this guide. Altair can show the sliders, but you need to add an alt.param to store the parameter. This can then be added to the chart.

gregory1506 commented 2 months ago

thanks.