Skip to content

Commit

Permalink
Fix handling of Plotly pane in Tabs (#2890)
Browse files Browse the repository at this point in the history
* Fix handling of Plotly pane in Tabs

* Fix flake

* Fix logic

* Add comment

* Update plotly test
  • Loading branch information
philippjfr authored Nov 6, 2021
1 parent 87bfb32 commit 25c708a
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 15 deletions.
16 changes: 12 additions & 4 deletions panel/layout/tabs.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,23 @@ def _get_objects(self, model, old_objects, doc, root, comm=None):
panels = self._panels[root.ref['id']]
for i, (name, pane) in enumerate(zip(self._names, self)):
hidden = self.dynamic and i != self.active
panel = panels.get(id(pane))
prev_hidden = (
hasattr(panel, 'child') and isinstance(panel.child, BkSpacer) and
panel.child.tags == ['hidden']
)
# If object has not changed, we have not toggled between
# hidden and unhidden state or the tabs are not
# dynamic then reuse the panel
if (pane in old_objects and id(pane) in panels and
((hidden and isinstance(panels[id(pane)].child, BkSpacer)) or
(not hidden and not isinstance(panels[id(pane)].child, BkSpacer)))):
panel = panels[id(pane)]
(not (hidden ^ prev_hidden) or not (self.dynamic or prev_hidden))):
new_models.append(panel)
continue
elif self.dynamic and i != self.active:

if hidden:
child = BkSpacer(**{k: v for k, v in pane.param.values().items()
if k in Layoutable.param and v is not None})
child.tags = ['hidden']
else:
try:
child = pane._get_model(doc, root, model, comm)
Expand Down
3 changes: 2 additions & 1 deletion panel/models/plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Defines a custom PlotlyPlot bokeh model to render Plotly plots.
"""
from bokeh.core.properties import (
Any, Dict, Either, Enum, Int, Instance, List, Null, Nullable, String
Any, Bool, Dict, Either, Enum, Int, Instance, List, Null, Nullable, String
)
from bokeh.models import LayoutDOM, ColumnDataSource

Expand Down Expand Up @@ -58,4 +58,5 @@ def __js_skip__(cls):
viewport = Either(Dict(String, Any), Null)
viewport_update_policy = Enum( "mouseup", "continuous", "throttle")
viewport_update_throttle = Int()
visibility = Bool(True)
_render_count = Int()
10 changes: 8 additions & 2 deletions panel/models/plotly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,15 @@ export class PlotlyPlotView extends PanelHTMLBoxView {
this.plot()
});
this.connect(this.model.properties.viewport.change, () => this._updateViewportFromProperty());
this.connect(this.model.properties.visibility.change, () => {
this.el.style.visibility = this.model.visibility ? 'visible' : 'hidden'
})
}

async render(): Promise<void> {
super.render()
this.el.appendChild(this._layout_wrapper);
this.el.style.visibility = this.model.visibility ? 'visible' : 'hidden'
this.el.appendChild(this._layout_wrapper)
await this.plot();
(window as any).Plotly.relayout(this._layout_wrapper, this.model.relayout)
}
Expand Down Expand Up @@ -389,6 +393,7 @@ export namespace PlotlyPlot {
viewport: p.Property<any>
viewport_update_policy: p.Property<string>
viewport_update_throttle: p.Property<number>
visibility: p.Property<boolean>
_render_count: p.Property<number>
}
}
Expand All @@ -407,7 +412,7 @@ export class PlotlyPlot extends HTMLBox {
static init_PlotlyPlot(): void {
this.prototype.default_view = PlotlyPlotView

this.define<PlotlyPlot.Props>(({Array, Any, Ref, String, Nullable, Number}) => ({
this.define<PlotlyPlot.Props>(({Array, Any, Boolean, Ref, String, Nullable, Number}) => ({
data: [ Array(Any), [] ],
layout: [ Any, {} ],
config: [ Any, {} ],
Expand All @@ -423,6 +428,7 @@ export class PlotlyPlot extends HTMLBox {
viewport: [ Any, {} ],
viewport_update_policy: [ String, "mouseup" ],
viewport_update_throttle: [ Number, 200 ],
visibility: [ Boolean, true],
_render_count: [ Number, 0 ],
}))
}
Expand Down
4 changes: 2 additions & 2 deletions panel/pane/plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,8 +375,8 @@ def _patch_tabs_plotly(viewable, root):
args.update({f'tabs_{tabs.id}': tabs})
active &= tabs.active == i

model.visible = active
code = f'try {{ model.visible = {condition}; }} catch {{ }}'
model.visibility = active
code = f'try {{ model.visibility = {condition}; }} catch {{ }}'
for tabs in parent_tabs:
tab_key = f'tabs_{tabs.id}'
cb_args = dict(args)
Expand Down
12 changes: 6 additions & 6 deletions panel/tests/pane/test_plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,16 @@ def test_plotly_tabs(document, comm):
cb1, cb2 = root.js_property_callbacks['change:active']
if cb1.args['model'] is model2:
cb1, cb2 = cb2, cb1
assert model1.visible
assert model1.visibility
assert cb1.args['model'] is model1
assert cb1.code == 'try { model.visible = (cb_obj.active == 0); } catch { }'
assert not model2.visible
assert cb1.code == 'try { model.visibility = (cb_obj.active == 0); } catch { }'
assert not model2.visibility
assert cb2.args['model'] is model2
assert cb2.code == 'try { model.visible = (cb_obj.active == 1); } catch { }'
assert cb2.code == 'try { model.visibility = (cb_obj.active == 1); } catch { }'

tabs.insert(0, 'Blah')
assert cb1.code == 'try { model.visible = (cb_obj.active == 1); } catch { }'
assert cb2.code == 'try { model.visible = (cb_obj.active == 2); } catch { }'
assert cb1.code == 'try { model.visibility = (cb_obj.active == 1); } catch { }'
assert cb2.code == 'try { model.visibility = (cb_obj.active == 2); } catch { }'

@plotly_available
def test_clean_relayout_data():
Expand Down

0 comments on commit 25c708a

Please sign in to comment.