-
Notifications
You must be signed in to change notification settings - Fork 142
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
[POC] Enable title in tiles #232
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -1,7 +1,7 @@ | ||||||||
import logging | ||||||||
from typing import List, Literal | ||||||||
|
||||||||
from dash import ctx, dcc | ||||||||
from dash import ctx, dcc, html | ||||||||
from dash.exceptions import MissingCallbackContextException | ||||||||
from plotly import graph_objects as go | ||||||||
|
||||||||
|
@@ -34,6 +34,7 @@ class Graph(VizroBaseModel): | |||||||
type: Literal["graph"] = "graph" | ||||||||
figure: CapturedCallable = Field(..., import_path=px) | ||||||||
actions: List[Action] = [] | ||||||||
_title: str = PrivateAttr() | ||||||||
|
||||||||
# Component properties for actions and interactions | ||||||||
_output_property: str = PrivateAttr("figure") | ||||||||
|
@@ -70,33 +71,49 @@ def __getitem__(self, arg_name: str): | |||||||
return self.type | ||||||||
return self.figure[arg_name] | ||||||||
|
||||||||
@_log_call | ||||||||
def pre_build(self): | ||||||||
try: | ||||||||
self._title = self.figure._CapturedCallable__bound_arguments["title"] | ||||||||
self.figure._CapturedCallable__bound_arguments["title"] = None | ||||||||
Comment on lines
+77
to
+78
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
You should never need to access a property that has its name mangled like that. In this case we actually have a public method which does the same thanks to Best not to modify the
to something like this:
Note one limitation of doing this is that users will no longer be able to edit the figure title through a parameter, but I'm ok with that. I just thought through various different ways to handle this (e.g. should we take the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very interesting. Just to jog my memory a bit, did we decide on implementing the tiles as presented here, ie as part of the I also remember that we discussed the title bit, but I cannot recall if we came to a conclusion. As for the two cases:
Now for the question of not updating titles through parameters, I am undecided. On the one hand I think this is a functionality that may be hardly if ever used, on the other hand, I think this introduces a dangerous pattern of not allowing parameters to target any argument. I think we previously discussed also a slightly less automated version:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, exactly 👍
Yes, that would not work. For me this is ok so long as all the
Agree this is a more robust approach because it also handles the case that you do not specify the title at all through an argument but still have a graph title, like this:
Here if you tried to extract title by The big problem with approach is that in order to get So it's doing something which is quick and easy and works in I guess 99% of cases vs. something which is wasteful but works in 100% of cases. I guess we could have some hybrid approach where first we try to do
I also don't much like it as a constraint, but I think the alternative will just be more complicated than is worth it. There are workarounds if people really want to do this (write an action/callback), but it wouldn't work as a pure This problem is equal for both approaches btw (using
This is also ok by me. It's certainly an easy solution and would work well (apart from the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good points! And very important point on the performance. I don't understand one thing though
All things considered I feel we may want to start with the third approach, and then we can still go either way if it is actually important. Maybe we end up liking it enough such that we do not need to force the automation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh yes sorry, you're right that the 3rd approach does indeed allow changing the title using a The biggest disadvantage I guess is that it looks a bit weird/confusing to have a title field in two places ( I'm happy to go with this as the solution anyway and see if anyone finds it awkward or if it's actually fine in reality. It's definitely the easiest solution. |
||||||||
except KeyError: | ||||||||
self._title = None | ||||||||
|
||||||||
@_log_call | ||||||||
def build(self): | ||||||||
# The empty figure here is just a placeholder designed to be replaced by the actual figure when the filters | ||||||||
# etc. are applied. It only appears on the screen for a brief instant, but we need to make sure it's | ||||||||
# transparent and has no axes so it doesn't draw anything on the screen which would flicker away when the | ||||||||
# graph callback is executed to make the dcc.Loading icon appear. | ||||||||
return dcc.Loading( | ||||||||
dcc.Graph( | ||||||||
id=self.id, | ||||||||
figure=go.Figure( | ||||||||
layout={ | ||||||||
"paper_bgcolor": "rgba(0,0,0,0)", | ||||||||
"plot_bgcolor": "rgba(0,0,0,0)", | ||||||||
"xaxis": {"visible": False}, | ||||||||
"yaxis": {"visible": False}, | ||||||||
} | ||||||||
|
||||||||
graph_div = html.Div( | ||||||||
children=[ | ||||||||
html.P(self._title, className="tile-title"), | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess |
||||||||
dcc.Loading( | ||||||||
dcc.Graph( | ||||||||
id=self.id, | ||||||||
figure=go.Figure( | ||||||||
layout={ | ||||||||
"paper_bgcolor": "rgba(0,0,0,0)", | ||||||||
"plot_bgcolor": "rgba(0,0,0,0)", | ||||||||
"xaxis": {"visible": False}, | ||||||||
"yaxis": {"visible": False}, | ||||||||
} | ||||||||
), | ||||||||
config={ | ||||||||
"autosizable": True, | ||||||||
"frameMargins": 0, | ||||||||
"responsive": True, | ||||||||
}, | ||||||||
className="chart_container", | ||||||||
), | ||||||||
color="grey", | ||||||||
parent_className="loading-container", | ||||||||
), | ||||||||
config={ | ||||||||
"autosizable": True, | ||||||||
"frameMargins": 0, | ||||||||
"responsive": True, | ||||||||
}, | ||||||||
className="chart_container", | ||||||||
), | ||||||||
color="grey", | ||||||||
parent_className="loading-container", | ||||||||
], | ||||||||
style={"height": "96%"}, # inline style to be removed | ||||||||
) | ||||||||
return graph_div | ||||||||
|
||||||||
@staticmethod | ||||||||
def _update_theme(fig: go.Figure, theme_selector: bool): | ||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it easy to do this in a validator for
title
rather thanpre_build
? If so then I think we should prefer that.