dash icon indicating copy to clipboard operation
dash copied to clipboard

[Feature Request] Target components with dcc.Loading

Open ndrezn opened this issue 3 years ago • 1 comments

Is your feature request related to a problem? Please describe. Generally, it can be frustrating that dcc.Loading will trigger a spinning animation when ANY of its nested components are in a callback. For instance, you might want a full-screen spinner to take over sometimes, but if you want a full-screen spinner takeover, that animation is going to run EVERY time that a callback in the app runs.... which is quite painful.

Describe the solution you'd like New properties for dcc.Loading, e.g. property= and/or component_id= (or similar) which make it possible to target specific nested component properties and component IDs.

The code to handle this would likely go here: https://github.com/plotly/dash/blob/dev/components/dash-core-components/src/components/Loading.react.js#L54-L57

And look something like:

if (loading_state.prop != this.props.property) {
     return this.props.children
}

Describe alternatives you've considered There isn't a good solution here. You can down-nest the loading spinner, but this might not be the right UX you're looking for in the app.

ndrezn avatar Feb 14 '22 12:02 ndrezn

@ndrezn you can try the AntdSpin() in my components library fac, set parameter listenPropsMode='include', then only every target defined in includeProps will trigger Loading animation, here is a simple example:


fac.AntdSpace(
    [
        fac.AntdButton('not in includeProps', id='spin-include-demo-input1', type='primary'),
        fac.AntdButton('in includeProps', id='spin-include-demo-input2', type='primary')
    ]
),

fac.AntdSpin(
    fac.AntdSpace(
        [
            fac.AntdText('not in includeProps nClicks: 0', id='spin-include-demo-output1', strong=True),
            fac.AntdText('in includeProps nClicks: 0', id='spin-include-demo-output2', strong=True)
        ],
        direction='vertical'
    ),
    listenPropsMode='include',
    includeProps=['spin-include-demo-output2.children'],
    text='running'
)
...
@app.callback(
    Output('spin-include-demo-output1', 'children'),
    Input('spin-include-demo-input1', 'nClicks'),
    prevent_initial_call=True
)
def spin_include_callback_demo1(nClicks):
    import time
    time.sleep(1)

    return f'not in includeProps nClicks: {nClicks}'


@app.callback(
    Output('spin-include-demo-output2', 'children'),
    Input('spin-include-demo-input2', 'nClicks'),
    prevent_initial_call=True
)
def spin_include_callback_demo2(nClicks):
    import time
    time.sleep(1)

    return f'in includeProps nClicks: {nClicks}'

CNFeffery avatar May 16 '22 13:05 CNFeffery

What about adding a new property to the component, e.g. loading_properties. Then

const isLoading = loading_state && loading_state.is_loading;

changes into

let isLoading = false;

if (loading_state && loading_properties) {
    const loadingProperty = loading_properties.find(([id, prop]) => {
        return id === loading_state.component_name && prop === loading_state.prop_name;
    });

    isLoading = loading_state.is_loading && !!loadingProperty;
} else if (loading_state) {
    isLoading = loading_state.is_loading;
}

where loading_properties is a list of tuples like [(<component_id>, <component_property>), (..)]. the idea is that the Loading spinner will only be shown if the component properties given in the list of tuples is loading. If the property is not specified, Loading should just do what it does now. I would like to test out above code, but I can't get the dev environment working for Dash.

Extra changes

To get above snippet working, update

type: spinnerType

to

type: spinnerType,
loading_properties

in the this.props call. Also add

    /**
     * List of tuples. Each tuple contains component id and the property name.
     * Loading spinner will be shown only if the specified component's property is loading.
     * If empty, the spinner will be shown if any property of any component is loading.
     */
    loading_properties: PropTypes.arrayOf(PropTypes.array),

to Loading.propTypes

aGitForEveryone avatar Jun 02 '23 13:06 aGitForEveryone

closed by #2760

Coding-with-Adam avatar Mar 11 '24 16:03 Coding-with-Adam