✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Percentage height of dcc.Loading children

Hi,

When a dcc.Loading has finished loading, the style is empty which means that children cannot access the % values for their height attribute.

In the below example the graph is not the expected 5% height (although the width is 70% as expected).

Is this a bug or is it possible to set a % height for the graph in the below example?

import dash
import dash_core_components as dcc
import dash_html_components as html

app = dash.Dash()

app.layout = html.Div(
        dcc.Loading(
            dcc.Graph(
                id='graph',
                style={
                    'height': '5%',
                    'width': '70%'
                }
            )
        ),
        style={
            'height':'calc(100vh - 16px)',
            'width':'calc(100vw - 16px)'
        }
    )

app.run_server()

Versions:

  • dash 1.13.4
  • dcc 1.10.1
  • html 1.0.3

Thanks

In our previous version of dash_core_components (1.6.0) we set the dcc.Loading attribute className='height-100' with the below css. This meant the height of the dcc.Loading div was 100% once loading was complete. This no longer seems to work in dcc 1.10.1.

.height-100{
    height: 100%
}

How do we use % heights inside a dcc.Loading?

Has anyone learned to solve this problem and properly use dcc.Loadings?

Thanks for bringing this up @jimhendy! This indeed looks like a regression to us, we’re discussing the fix here: https://github.com/plotly/dash-core-components/issues/831

1 Like

Thanks @chriddyp, much appreciated.

We developed a workaround for this by updating the dash versions but using a custom version of dcc.Loading built from the cookiecutter boilerplate.

I’ve included the javascript for the curious, hopefully something like this can be included in dash_core_components soon.

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import GraphSpinner from '../fragments/DashCustomLoading/spinners/GraphSpinner.jsx';
import DefaultSpinner from '../fragments/DashCustomLoading/spinners/DefaultSpinner.jsx';
//import CubeSpinner from '../fragments/DashCustomLoading/spinners/CubeSpinner.jsx'; // npm compilation issues for some reason
import CircleSpinner from '../fragments/DashCustomLoading/spinners/CircleSpinner.jsx';
import DotSpinner from '../fragments/DashCustomLoading/spinners/DotSpinner.jsx';

function getSpinner(spinnerType) {
    switch (spinnerType) {
        case 'graph':
            return GraphSpinner;
    
        case 'circle':
            return CircleSpinner;
        case 'dot':
            return DotSpinner;
        default:
            return DefaultSpinner;
    }
}


/*
case 'cube':
            return CubeSpinner;

*/
const hiddenContainer = {visibility: 'hidden', position: 'relative'};

const coveringSpinner = {
    visibility: 'visible',
    position: 'absolute',
    top: '0',
    height: '100%',
    width: '100%',
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
};

/**
 * A DashCustomLoading component that wraps any other component and displays a spinner until the wrapped component has rendered.
 */
export default class DashCustomLoading extends Component {
    render() {
        const {
            loading_state,
            color,
            className, // Applied to parent div - inconsistent but allows backward compatibility
            style, // Applied to the loading state
	    loadingClassName, // Loading state
	    parentStyle, // Parent div
            fullscreen,
            debug,
            type: spinnerType,
        } = this.props;

        const isLoading = loading_state && loading_state.is_loading;
        const Spinner = isLoading && getSpinner(spinnerType);

        return (
		<div className={className} style={isLoading ? hiddenContainer : parentStyle }>
                {this.props.children}
                <div style={isLoading ? coveringSpinner : {}}>
                    {isLoading && (
                        <Spinner
                            className={loadingClassName}
                            style={style}
                            status={loading_state}
                            color={color}
                            debug={debug}
                            fullscreen={fullscreen}
                        />
                    )}
                </div>
            </div>
        );
    }
}

DashCustomLoading._dashprivate_isLoadingComponent = true;

DashCustomLoading.defaultProps = {
    type: 'default',
    color: '#119DFF',
};

DashCustomLoading.propTypes = {
    /**
     * The ID of this component, used to identify dash components
     * in callbacks. The ID needs to be unique across all of the
     * components in an app.
     */
    id: PropTypes.string,

    /**
     * Array that holds components to render
     */
    children: PropTypes.oneOfType([
        PropTypes.arrayOf(PropTypes.node),
        PropTypes.node,
    ]),

    /**
     * Property that determines which spinner to show
     * one of 'graph', 'cube', 'circle', 'dot', or 'default'.
     */
    type: PropTypes.oneOf(['graph', 'cube', 'circle', 'dot', 'default']),

    /**
     * Boolean that makes the spinner display full-screen
     */
    fullscreen: PropTypes.bool,

    /**
     * If true, the spinner will display the component_name and prop_name
     * while loading
     */
    debug: PropTypes.bool,

    /**
     * Additional CSS class for the spinner root DOM node
     */
    className: PropTypes.string,

    /**
       * class name for loading state only, the parent div style can be set using "style".
       */
    loadingClassName: PropTypes.string,

    /**
       * Additional CSS styling for parent div, persisted after loading is complete
       */
    parentStyle: PropTypes.object,

    /**
     * Additional CSS styling for the spinner root DOM node
     */
    style: PropTypes.object,

    /**
     * Primary colour used for the loading spinners
     */
    color: PropTypes.string,

    /**
     * Object that holds the loading state object coming from dash-renderer
     */
    loading_state: PropTypes.shape({
        /**
         * Determines if the component is loading or not
         */
        is_loading: PropTypes.bool,
        /**
         * Holds which property is loading
         */
        prop_name: PropTypes.string,
        /**
         * Holds the name of the component that is loading
         */
        component_name: PropTypes.string,
    }),
};