posit-dev / py-shiny

Shiny for Python
https://shiny.posit.co/py/
MIT License
1.3k stars 78 forks source link

Guide To Busy Indicator Use? #1433

Closed gfleetwood closed 5 months ago

gfleetwood commented 5 months ago

Hello,

I'm trying to use the busy indicator feature incorporated here, but its behavior is seemingly erratic. Sometimes it works, and other times it doesn't. After looking through the examples I'm still not clear on how to make it work consistently:

This is the structure of the code I wan't to use the feature in. When a button is clicked the code fetches dataframes from several sources and displays them on the UI. How do I use the busy indicator feature to always have a loading symbol as each bit of information is gathered?

from shiny import App, reactive, render, req, ui
from shiny.ui import TagList, div, h3, head_content, tags
import pandas as pd 
import requests

def server(input, output, session):

    @render.data_frame
    @reactive.event(input.search_button)
    def get_df():

        server_endpoint = 'https://'
        payload_in = {'search_term': input.search_term().strip()}

        #ui.busy_indicators.options(spinner_type = 'ring'),
        #ui.busy_indicators.use(spinners = "ring"),
        response = requests.post(server_endpoint, json = payload_in)
        payload_out = response.json()['data']
        result = render.DataGrid(pd.DataFrame(json.loads(payload_out)), width = '1000px') 

        return(result)

    @render.data_frame
    @reactive.event(input.search_button)
    def get_df2():

        server_endpoint = 'https://'
        payload_in = {'search_term': input.search_term().strip()}

        #ui.busy_indicators.options(spinner_type = 'ring'),
        #ui.busy_indicators.use(spinners = "ring"),
        response = requests.post(server_endpoint, json = payload_in)
        payload_out = response.json()['data']
        result = render.DataGrid(pd.DataFrame(json.loads(payload_out)), width = '1000px') 

        return(result)

app_ui = ui.page_fluid(

    #ui.busy_indicators.options(spinner_type = 'ring'),
    #ui.busy_indicators.use(spinners = "ring"),

    ui.input_text('search_term', 'Enter Search Term'),
    ui.input_action_button('search_button', 'Search'),    
    ui.output_data_frame('get_df'),
    ui.output_data_frame('get_df2'),
)

app = App(app_ui, server)

@cpsievert

cpsievert commented 5 months ago

Are you able to screen share the behavior you're seeing and/or provide search terms that I can enter into the example to replicate you're seeing?

Here's a more minimal version of this app (without the requests to an unknown endpoint) that works as expected.

BTW, as pointed out in the docs, make sure to always include busy_indicators.options() and busy_indicators.use() in the UI (calling them that way in the @render.data_frame decorator won't do anything). Also, .use() only supports boolean values as it's for altogether disabling/enabling the spinners/pulse

gfleetwood commented 5 months ago

@cpsievert Can I privately message you a video or screenshot? The actual app is a bit sensitive.

I was trying to use the feature - pip installing from git - before it was on pypi and the docs went up, but now I have an understanding of how it should be used. That's what I wasn't sure about before, so it was hard to know where the erroneous behavior was coming from.

What i just noticed is that the busy indicators always work when I test the app locally. The problem occurs when I deploy it to Modal (https://modal.com/). So now I know that's where I should be looking.

On another note, do you know anyone who does Shiny For Python consulting?

cpsievert commented 5 months ago

Can I privately message you a video or screenshot?

Of course: cpsievert1@gmail.com

gfleetwood commented 5 months ago

@cpsievert OK, I sent an email over.

cpsievert commented 5 months ago

To summarize the email thread, after updating shiny on the hosted environment, the issue went away