Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

Concatenating Dash inputs to a list or dictionary

I am only mildly experienced in Python, but I have been trying to learn quickly. Forgive me for asking any naïve questions. Or failing at formatting this post.

I would like to create a Dash app that has user inputs for the number of players as well as the names for each of these players. For this task I followed the discussion in this thread Dynamic number of inputs based on anther input - #14 by nedned

I was able to use the previous discussion to dynamically create entry fields for each of the player names, where the number of entry fields depends on the number entered by the user. I am having trouble figuring out how to take each name entered in a field and place them as headings in the appropriate column of a summary table. I have considered the use of JSON data in a hidden div, but I’m not sure how to retrieve the entered name for each of the Dash inputs and place them in a central repository. I have simplified my overall code below. Any tips would be so appreciated!

import numpy as np
import dash
import json
import plotly.graph_objs as go
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output, State
import pandas as pd

# Model-wide constants
MAX_PEOPLE = 16

InputStyle = {"padding": "20px"}

PlayerNames = dict([("Player {}".format(n),n) for n in range(1, MAX_PEOPLE +1)])

slots = []
for S in range(1, 13): slots.append(" ".join(["Slot ", str(S)]))


app = dash.Dash()

app.layout = html.Div([
            html.H1("Testing"),
            html.Div([html.Label("How many golfers are there?"),
                            dcc.Input(id = "PlayersInput",
                                      placeholder = "# of people",
                                      value = 2,
                                      type = "number",
                                      min = 1,
                                      max = MAX_PEOPLE)]),
            
            html.Hr(),
            html.H1("Enter the names of all players"),
            html.Div(
                id = "Player_Names_Input_Box",
                children = [
                        html.Div(
                            id = "PI_{}_container".format(i),
                            children = [
                                "Player {} Name:     ".format(i),
                                dcc.Input(
                                    id = "PI_{}".format(i),
                                    placeholder = "Enter name",
                                    type = "text"),
                                ]) for i in range(1, MAX_PEOPLE +1)]),
                                        
            html.Div(html.H1("Here is the schedule")),

            html.Div(id = "Table"),
            
            # Planning to have hidden div to store data

])

#Defining visibility of Player [name] Inputs (PI's)
for n in range(1, MAX_PEOPLE+1):
    @app.callback(Output("PI_{}_container".format(n), "style"),
                         [Input("PlayersInput", "value")])
    def callback(players, n = n):
        NewStyle = {**InputStyle}
        if n <= players:
            NewStyle["display"] = "block"
        else:
             NewStyle["display"] = "none"
        return NewStyle


@app.callback(
        Output("Table", "children"),
            [Input("PlayersInput", "value")])
def update_table(NumPeople):
    display = np.zeros((NumPeople,NumPeople))
    slots = []
    for S in range(1, NumPeople +1): slots.append(" ".join([str(S)]))
    fig = dcc.Graph(id = "Chart",
                figure = {
                    "data": [go.Table(
                                header = dict(values = slots),
                                cells = dict(values = display,
                                         align = ["center"]))
                                ]})
    return fig

"""
I was planning on using a callback of this sort to retrieve all of the player
names and assemble a dictionary to pass back to Dash.

@app.callback(Output("names-storage", "value"),
              [Input("PI_{}", "value") for n in range(1, MAX_PEOPLE+1)])
def updatePlayerDict
"""

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

FWIW, the new way to do this kind of app is with our new pattern matching callbacks feature :slightly_smiling_face: : https://dash.plotly.com/pattern-matching-callbacks