-
Notifications
You must be signed in to change notification settings - Fork 945
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
Creating views for generic HasTraits models #2296
Comments
Putting to minor release, in case we add the introspecting convenience functions. Adding docs documenting this pattern is a patch release, of course. |
Thanks for bringing this to my attention, Jason. I'd be very happy to see this paradigm spread to traitlets/ipywidgets! I'd go further and claim that the missing functions aren't just about convenience, they are about encapsulation, with major implications. Here, the FXWidgetView class had to be built specifically for viewing the FXModel, because it relies on knowing domain-specific details like the name and type of each of the FXModel widgets. If traits are then added to or deleted from or renamed in FXModel, the corresponding GUI code needs to be updated for it to keep working. As a result, anyone who modifies FXModel has to learn about ipywidgets, has to know FXWidgetView exists and where to find it, and has to make sure to update and test FXWidgets on every change to FXModel. Thus without the convenience functions, the domain-specific code (FXModel) has to be maintained in lockstep with the GUI code (FXWidgetView). I think tying the GUI and model code together like that is a problem because the same model code might be applicable to many contexts (command-line, batch, Jupyter notebooks, native GUIs) and because the people with expertise to update the model aren't necessarily the people with GUI expertise or interest. As a trivial example of the alternative approach of rigorously separating the model and GUI code, you can see the NYCTaxiExplorer class in nyc_taxi_panel, which is equivalent to FXModel in that it declares attributes and how they relate to each other. But then generating the specific widgets involved does not require any GUI code; you just pass the model instance to Panel) and Panel does the rest. All the information needed to build the GUI is declared in the model class, but without tying it to any particular domain-specific GUI implementation. The Param library that supports this is very similar to Traitlets in functionality, but it was designed from the start to support a complete break between the model and the GUI (view+controller) code. Over the years there have been many different GUI toolkits supported for Param (Tk, ipywidgets, Bokeh, and now Panel), but the same domain-specific Param code from 2004 still works (as designed!). E.g. the large class hierarchy from ImaGen, written in 2005, worked as-is with Panel when we wrote Panel a few months ago. You can see a similar but self-contained example of a complex hierarchy in the attractors dashboard, with new attributes added as needed for each class and new GUI-editable subclasses that can be added without changing the GUI code at all. Depending on users' needs, implementing this approach for Traitlets could take a few different forms. Panel currently works this way only for Parameterized objects, but it could be extended to provide similar functionality for HasTraits objects. Panel's support for Parameterized objects is only 500 lines (in panel/param.py), so adding similar support for HasTraits might not be a huge job, though since Panel was explicitly built around Param there will probably be some friction with how Traitlets does things. Plus our own knowledge of Param is much deeper than our knowledge of Traitlets, so it would take us some time to figure out the differences. The advantage of extending Panel in this way would be that HasTraits objects could then be GUI-editable both in a Jupyter notebook and in a separate standalone dashboard, because of Panel being built on Bokeh's widgets that work the same in notebook and deployed-server contexts. What you're proposing here is different, of course, i.e. making HasTraits objects editable in a Jupyter notebook using ipywidgets, which makes it parallel to Param+Panel instead of using any part of what we developed. But we at HoloViz would be very happy for the ipywidgets team to adopt and guide people to working in that style, because of all the benefits that it gives independent of any particular toolkit. If that approach took off in the ipywidgets world, we'd be very likely to eventually add HasTraits support to Panel so that users' domain-specific code would be as broadly applicable as possible. Meanwhile, we'd be happy to provide any help or feedback we could on any work you are doing in this area... |
Good Example, well done. However I tried to make an HTML page out of it, using 'from ipywidgets.embed import embed_minimal_html'. As background, I'm working on a 'ipyleaflet' app. But 'traitlets link' does not work. What needs to be changed to use 'widgets.jslink' instead? Links with 'widgets.jslink' work in HTML exports. |
An excellent question on StackOverflow is about defining ipywidget views for a Traits model. This is a pattern that I think would be good to include in the documentation (though perhaps a simplified version...):
Setup
From the StackOverflow post:
View
So here's how to make a custom view using ipywidget views, using the widgets from the post. The key is the
link
calls to bind attributes to widget values.I'll point out that Param has been advocating this sort of separation for a while, and @jbednar has pointed out that ipywidgets could implement convenience functions to support this pattern as well. I think that's a good idea - to have some simple convenience functions that are a step up from the interact functions that take a HasTraits class, introspect it, and provide default widgets for different traits for common cases.
The text was updated successfully, but these errors were encountered: