Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

Line breaks in text that changes dynamically?

I’m a beginner coder, so please pardon the basicness of the following questions…

I’ve been trying to figure out a good way to pull up a “dynamic index card” of info on a dash application.

For example, let’s say I have a set of companies stored in a dataframe.

import pandas as pd
import numpy as np

df = pd.DataFrame({ 'company' : ['Big', 'Blue', 'Waffle', 'Schmoo'],
                   'product' : ['apples', 'shoelaces', 'ice', 'anxiety'],
                   'employees' : [2, 4, -1, 70]
                    })
df= df.set_index('company')
df

image

What I would like to be able to do is select a company name from a dropdown menu, and generate a little report about that company. For example:

Company name: Blue
Number of employees: 4
Main product: shoelaces

However, I’m having trouble getting line breaks in the text.

Below is what I tried:

import dash
import dash_core_components as dcc
import dash_html_components as html

import pandas as pd
import numpy as np

df = pd.DataFrame({ 'company' : ['Big', 'Blue', 'Waffle', 'Schmoo'],
                   'product' : ['apples', 'shoelaces', 'ice', 'anxiety'],
                   'employees' : [2, 4, -1, 70]
                    })
df= df.set_index('company')

inv_options = df.index

app = dash.Dash()

app.layout = html.Div([
    html.H2('Company Report'),
    html.Div(
        [
            dcc.Dropdown(
                id='Company', # 'id' is also the column name in df
                options=[{
                    'label':i,
                    'value':i
                } for i in inv_options],
                value ='Blue'),
        ],
        style={'width': '25%',
                'display': 'inline-block'}),
    dcc.Markdown(id ='report-text')

])

@app.callback(
    dash.dependencies.Output('report-text', 'children'),
    [dash.dependencies.Input('Company', 'value')])
def callback_text(Company):
    investor_str = '''Company name: {0}
Number of employees: {1}  
Main product: {2}'''.format(
    Company,
    df.loc[Company, 'employees'],
    df.loc[Company, 'product']
    )

    return investor_str

if __name__ == '__main__':
    app.run_server(debug=True)

The result is:

image

I know that Markdown requires two spaces after a line to start a new line, but for some reason the spaces in the string code after Company name: {0} disappear whenever I save the file.

I also tried to use html.Div() instead of dcc.Markdown, but I couldn’t figure out how to create line breaks without creating a new callback for each line.

In the end, I decided to create a temporary pandas dataframe and generate an html table from that as described in the User Guide.

However, I’m still curious, is there a good way to create line breaks in text used within html.Div() or html.P()?

Yep, there’s plenty of ways to achieve this in HTML. (In general with layout needs such as this, you can approach the problem as if you’re creating regular HTML and then create the Dash code which will generate that.

In HTML there is a <br> tag that inserts a break, however the best way to do what you’re after is just to put your text in different block level elements (which are rendered on different lines in HTML, as opposed to an element like <span> which is not). This could be with simple <div> tags, but here I would go for <p> tags which are meant to wrap text. Like this:

<div>
   <p>Company name: Blue</p>
   <p>Number of Employees: 4</p>
</div>

Then the corresponding Dash layout tree you could return from your callback would be:

html.Div([
    html.P("Company name: {}".format(df.loc[Company, 'employees'])),
    html.P("Number of Employees: {}".format(df.loc[Company, 'product']))
])
2 Likes

Thanks for the example, very helpful!

1 Like