jupyter / dashboards_server

[RETIRED] Server that runs and renders Jupyter notebooks as interactive dashboards
Other
181 stars 48 forks source link

Button which rerunns all cells in jupyter notebook does not work on dashboard server #300

Closed romario076 closed 7 years ago

romario076 commented 7 years ago

Hi ! We have multi cell notebook wich requires one input - Date, and each time the input is changed i need to rerun all cells with code to generate new outputs. I use grid dashboard layout. The button works in jupyter notebook dashboard however it does not work when i deploy my notebook to dashboard server.

Here is the code .

image

I get following error in browser after clicking on button on dashboard server. capture

If you know any solution for reruning all notebook cells on deployed app with one input parameter. Please help to find any solution.

parente commented 7 years ago

Hi @romario076 . The custom require calls you're making in your notebook are not supported in the dashboard server which does not have the notebook JS modules. I'm not sure it ever will since it's building off of the new Jupyter Lab components rather than embedding all of the classic notebook JS files.

We need to do a better job of scoping and documenting what can work in the dashboard server, what cannot but could with improvements, and what will probably never work.

bowenli37 commented 7 years ago

We used ipywidgets.interact to achieve the same behavior, that is, to allow user to update dashboards by providing inputs on dashboards server.

class Model:
    @classmethod
    def load_data(self):
        # Load data from somewhere
        return data

class Controller:
    def __init__(self):
        self.data = Model.load_data()
        self.widgets = OrderedDict({
            'widget': widget(self)
        })
        # it is a hidden element to trigger show()
        self.trigger = Checkbox(value = False,
                                description='',
                                layout=Layout(visibility='hidden'))
        display(self.widgets['widget'].form)
        interact(self.show, x = self.trigger)

    def button_action(self):
        # change trigger
        self.trigger.value = not self.trigger.value

    def plot1(self):
        # do plot1
        return

    def plot2(self):
        # do plot2
        return

    def show(self, x):
        self.plot1()
        self.plot2()

class widget:
    # pass controller to constructor
    def __init__(self, controller):
        # build a form with ipywidgets elements
        # suppose you have a button that triggers refresh
        button = Button(description = 'Click to update', button_style = 'info')

        # Form event
        def button_handler(sender):
            controller.button_action()

        button.on_click(button_handler)

To display the dashboards, just do

controller = Controller()

Then you have to restructure your cells into functions like Controller.plot1(). This way you don't need to rerun all the cells, just one function Controller.show(). It breaks our usual coding pattern as in an interactive notebook, but this is as close as we can get if we want to achieve the desired behavior.

parente commented 7 years ago

@bowenli37 thanks for sharing that recipe.

There's also been work (https://github.com/jupyter/jupyter_client/issues/209) to support an update_display message as part of the Jupyter protocol which should make updating cell outputs easier in the future.

dwkenefick commented 7 years ago

Hi all, Sorry to comment on something long dead, but I have a similar problem and nothing seems to be working.

I have a dashboard with a single set of inputs, and I would like those inputs to update charts in several different cells. I can use a Javascript call in a notebook, but this does not work once the dashboard is deployed.

Things I've tried:

def update_chart(plotting_object): chart_container.clear_output() with chart_container: plotting_object.plot()

Later Cell: handler function

def button_handler(sender): update_chart(plotting_object)


This works fine in the notebook and dashboard preview, but the charts do not update once the dashboard is deployed.
* `IPython.display.update_display`:  In the cell containing each chart, I use `display` to show each chart and provide a `display_id`.  Once the inputs are updated, a handler function calls `update_display` on each `display_id` with the new chart.  Once the dashboard is deployed, the cells containing the charts do not update.
* @bowenli37's recipe:  This too does not seem to work:  the trigger does not seem to work once the dashboard is deployed.  Even in the notebook, the charts appear in the cell where I called `controller = Controller()` rather than `controller.plot1()`

I want to arrange the charts nicely in a grid format, so running everything from a single cell probably wont work.  I could also have a separate submit button for each chart (which works) but would be obnoxious.  

Ultimately, I need to trigger a display update for one cell from another cell while the dashboard is running.  Can anyone see flaws in my general approach, or suggest something that will give me equivalent results?  

Let me know if I can clarify, or if I should open another issue.  
funnydevnull commented 6 years ago

@dwkenefick have you had any luck with this? I'm in exactly the same position and I've tried similar solutions to no avail. I've found some ipywidget discussion (issue 1410) about the fact that the Output widget is not supported in the context of embedded HTML (which I presume is what the dashboard is). There they claim that its been fixed but this is quite recent and I'm not sure the fix has made it into the current distribution. Can anyone who understands this better comment on whether this fix will likely resolve @dwkenefick's (and my) problem?