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

dynamic forms in solara #512

Open
tharwan opened this issue Feb 21, 2024 · 10 comments
Open

dynamic forms in solara #512

tharwan opened this issue Feb 21, 2024 · 10 comments
Assignees
Labels
documentation Improvements or additions to documentation

Comments

@tharwan
Copy link

tharwan commented Feb 21, 2024

We would like to display dynamic forms in our solara frontend based on pydantic models / json schemas.

There are multiple IPyWidgets out there that provide this functionality namely:

However both currently do not seem to be compatible with solara. Mainly because they do not directly provide a widget but rather create and manage exisiting widgets. Therefore they do not have the option to use .element for initialisation.

Do you have any hints on how to best cover this use case?
Should the packages provide a proper widget?
Would it be sufficient to be able to swap the widget classes for the corresponding solara ones? e.g. sl.InputText for IPyWidgets.Text
Is there a good way to mix "traditional" IPyWidgets with reactive ones?

@swelborn
Copy link

Unsure if this helps, but I added a very basic implementation of forms to this effect here:

https://github.com/swelborn/tomopyui/blob/b3306ff2e31dd2ee34614c77187de1f98ef9df8d/tomopyui/frontend/components/metadata/metadata.py

It uses pydantic to do this, and pydantic models can be autogenerated from json schema (https://docs.pydantic.dev/latest/integrations/datamodel_code_generator/). It's in a very WIP PR to that repo.

@maartenbreddels
Copy link
Contributor

@swelborn very interesting it reminder me of code that I saw from @Jhsmit
Maybe it makes sense to have a form+pydantic example at the solara website?

@Jhsmit do you also have a link to your version?

@maartenbreddels
Copy link
Contributor

On the topic of mixing classic widgets with components, this might be a good example on how to add a classic widget in a component (in this case ipyautoui cc @jgunstone):

import solara
from pydantic import BaseModel, Field
from ipyautoui import AutoUi

class LineGraph(BaseModel):
    """parameters to define a simple `y=m*x + c` line graph"""
    title: str = Field(default='line equation', description='add chart title')
    m: float = Field(default=2, description='gradient')
    c: float = Field(default=5, ge=0, le=10, description='intercept')
    x_range: tuple[int, int] = Field(
        default=(0,5), ge=0, le=50, description='x-range for chart')
    y_range: tuple[int, int] = Field(
        default=(0,5), ge=0, le=50, description='y-range for chart')



@solara.component
def Page():
    # important to use a widget component, not a function component
    container = solara.v.Html(tag="div")#, children=[])
    # this will reset the children (possibly a bug in reacton)
    # container = solara.Column()
    def add_classic_widget():
        # generate your normal widget
        ui = AutoUi(schema=LineGraph)
        # add it to the generated widget by solara/reacton
        container_widget = solara.get_widget(container)
        container_widget.children = (ui,)

    solara.use_effect(add_classic_widget, dependencies=[])
    return container

One worry is that this does not close the AutoUi widget, and might result in a (temporary) memory leak. It's temporary because all widgets belonging to a virtual kernel will be closed once the virtual kernel will be closed (on browser/page close or kernel cull timeout - default 24h https://solara.dev/docs/understanding/solara-server )

Does it make sense to have this example at https://solara.dev/docs/howto/ipywidget-libraries ?

@Jhsmit
Copy link
Contributor

Jhsmit commented Feb 27, 2024

the one i made is here:
https://github.com/Jhsmit/awesome-solara/blob/master/examples/input_form.py

havent used it in a while though

@swelborn
Copy link

nice @Jhsmit

one note for people reading this: code in @Jhsmit is that use of fields and .dict() is deprecated in newer versions of pydantic:

The getter for property "__fields__" is deprecated
  The `__fields__` attribute is deprecated, use `model_fields` instead.
The method "dict" in class "BaseModel" is deprecated
  The `dict` method is deprecated; use `model_dump` instead.

@Jhsmit
Copy link
Contributor

Jhsmit commented Feb 27, 2024

thanks @swelborn, i might update it
did you try it? does it work otherwise?

@jgunstone
Copy link

jgunstone commented Feb 27, 2024

@maartenbreddels - thanks for the mention -
If possible I'd like ipyautoui to be better supported in solara. maxfordham/ipyautoui#289

as an almost exclusive rule in ipyautoui widgets are instantiated as below.
traits are observed to change widget behaviour

class MyWidget(w.VBox):
    my_trait = tr.Unicode()
    def __init__(self, **kwargs):
        # pre-init code
        super().__init__(**kwargs)
        # post-init code

I had an initial quick look at your code-gen tool...
my understanding is that it reads the traits and converts them to typed kwargs ?
so my hope is with a bit of work I could make it work...
I had an initial stab:
maxfordham/ipyautoui#291

a v simple widget worked fine (SaveButtonBar).... but the more complex ones didn't...

you got any hot tips?

@tharwan
Copy link
Author

tharwan commented Feb 28, 2024

Does it make sense to have this example at https://solara.dev/docs/howto/ipywidget-libraries ?

having recently tried to prototype something with solara this would help tremendously, but for sure needs to have some context of when to apply it.

@maartenbreddels
Copy link
Contributor

I think either ipyautoui is completely using reacton/solara, it we should just advice to use the above example. I have some ideas how we can make it easier to use widgets in a component directly (With a proper memory cleanup phase), but for now the above will suffice.
I'll try to add it to the docs soon!

@maartenbreddels maartenbreddels self-assigned this Feb 28, 2024
@maartenbreddels maartenbreddels added the documentation Improvements or additions to documentation label Feb 28, 2024
@swelborn
Copy link

@Jhsmit Sorry I didn't give it a go, I just pulled into vscode and noticed the deprecation warnings (which show as the function crossed through inline).

maartenbreddels added a commit that referenced this issue Mar 1, 2024
We also give specific examples for ipyaggrid and ipydatagrid which
are quite popular with solara.

Based on discussion on discord and:
 #512
 #511
maartenbreddels added a commit that referenced this issue Mar 10, 2024
We also give specific examples for ipyaggrid and ipydatagrid which
are quite popular with solara.

Based on discussion on discord and:
 #512
 #511
maartenbreddels added a commit that referenced this issue Apr 15, 2024
We also give specific examples for ipyaggrid and ipydatagrid which
are quite popular with solara.

Based on discussion on discord and:
 #512
 #511
maartenbreddels added a commit that referenced this issue Apr 15, 2024
We also give specific examples for ipyaggrid and ipydatagrid which
are quite popular with solara.

Based on discussion on discord and:
 #512
 #511
maartenbreddels added a commit that referenced this issue Apr 15, 2024
We also give specific examples for ipyaggrid and ipydatagrid which
are quite popular with solara.

Based on discussion on discord and:
 #512
 #511
maartenbreddels added a commit that referenced this issue Apr 15, 2024
We also give specific examples for ipyaggrid and ipydatagrid which
are quite popular with solara.

Based on discussion on discord and:
 #512
 #511
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

5 participants