Get the user inputs in JSON

Hi,
I’m newbie to dash and I’m really excited to use it for my thesis. This is how my dash layout would look,

In Model definitions tab, I’ve several inputs as shown in figure. Those user inputs I want to get into a JSON. This JSON would be passed as an argument to API developed in python.

Here is my code to get the layout.

import dash
import dash_html_components as html
import dash_core_components as dcc
import json

from dash.dependencies import Input, Output, State

app = dash.Dash(__name__)

tabs_styles = {'height': '54px'}

tab_style = {
    'borderBottom': '1px solid #d6d6d6',
    'padding': '6px',
    'fontWeight': 'bold',
    'textAlign':'center'
}

tab_selected_style = {
    'borderTop': '1px solid #d6d6d6',
    'borderBottom': '1px solid #d6d6d6',
    'backgroundColor': '#119DFF',
    'color': 'white',
    'padding': '6px'
}

app.layout = html.Div([
    html.H1('Optimizer', style={'textAlign': 'center', 'color': '#FFA500'}),
    dcc.Tabs(id="tabs-styled-with-inline", value='tab-1', children=[
        dcc.Tab(label='Model definition', value='tab_model', style=tab_style, selected_style=tab_selected_style),
        dcc.Tab(label='Universe definition', value='tab_univ', style=tab_style, selected_style=tab_selected_style),
        dcc.Tab(label='Back testing', value='tab_backT', style=tab_style, selected_style=tab_selected_style),
    ], style=tabs_styles),
    html.Div(id='tabs-content-inline')
])


@app.callback(Output('tabs-content-inline', 'children'),
              [Input('tabs-styled-with-inline', 'value')])
def render_content(tab):
    if tab == 'tab_model':
        tab_model_app = html.Div([
            html.Div([
                html.H4('Optimization goal'),
                dcc.Dropdown(
                    id='opt_goal',
                    options=[
                        {'label': 'Return Max', 'value': 'return_max'},
                        {'label': 'MV Objectives', 'value': 'mv_obj'}],
                    style=dict(width='40%', verticalAlign='middle'))
            ]),

            html.H4('Select constraints'),
            html.Div([html.Label('Holding weights', style={'marginRight': 25}),
            dcc.Input(id='holding_wt_lower', type="number", placeholder="Lower bound", min=0.05, max=0.3,
                      style={'width': 100, 'marginRight': 25}),
            dcc.Input(id='holding_wt_upper', type="number", placeholder="Upper bound", min=0.05, max=0.3,
                      style={'width': 100, 'marginRight': 25, 'marginBottom': 10})
            ]),

            html.Div([html.Label('Fully invested', style={'marginRight': 25}),
                      dcc.Input(id='fully_invested_lower', type="number", placeholder="Lower bound", min=0.05, max=0.3,
                                style={'width': 100, 'marginRight': 25}),
                      dcc.Input(id='fully_invested_upper', type="number", placeholder="Upper bound", min=0.05, max=0.3,
                                style={'width': 100, 'marginRight': 25, 'marginBottom': 10})
                      ]),

            html.Div([html.Button(id='reset-button', n_clicks=0, children='Reset', style={'fontWeight': 'bold',
                        'textAlign':'center', 'marginRight': 25}, title='Click to clear the inputs'),
                        html.Button(id='submit-button', n_clicks=0, children='Submit', style={'fontWeight': 'bold',
                        'textAlign':'center', 'marginRight': 25}, title='Click to optimize')
                     ]),

        html.Div(id='output-container')])

        return tab_model_app

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

How can I get the user inputs in JSON?

Your userinput just consists of numbers right?
I don’t know to much about json, so maybe I am wrong, but you have put the type=“number”.
You could just use it as type=“text” which should than give you a string, which should not be different from
converting the number to json.

Otherwise you could do it like that:

@app.callback(Output('user_output', 'children').
[Input('fully_invested_lower', 'value')

def convert_to_json(value):
   return json.dumps(value)

But this seems unnecessary

Thank you @Snizl for helping me out.
There would be 5 more such dropdown menus and inputs. All I want to do is to dump them into JSON and not just fully_invested_lower .
I also have 3 tabs in superior html div.

As I said, I think simply changing their type property to “text” should already do it.
Otherwise you can simply add the other inputs to the callback.

Actually I see that you have a submit button(and a reset button) as well, so you should rather pass the values as a state in that case:

@app.callback(
#give as outputs wherever you want to store the values from the user input
[Output('user_output', 'children'),
Output('second_output', 'children'),
Output('third output', 'children')],
#give as inputs everything that you want to trigger the callback
[Input('submit-button', 'n_clicks'),
Input('reset-button', 'n_clicks'],
#give each user input as a seperate state
[State('fully_invested_lower', 'value'),
State('second_input', 'value'),
State('third_input, 'value')])

def convert_to_json(submit, reset, first_input, second_input, third_input):
    ctx= dash.callback_context    
    #check where you got the input from, to know if you want to pass the values or reset
    if ctx.triggered[0]['prop_id']=='submit-button.n_clicks':
         #repeat the next line for each user inout 
         output_one=json.dumps(first_input)
         
    if ctx.triggered[0]['prop_id']=='reset-button.n_clicks':
        #do here whatever you want to do in case of a reset
   return  output_one, output_two, output_three

This looks like some promising code. I want to try this out.
Thank you so much @Snizl :slight_smile:

Tried that but it didn’t serve my purpose. What I actually want to export JSON as following for above mentioned inputs,

{
	"Optimization goal":"MV Objectives",
	"Holding weights":[{ "holding_wt_lower":"0.01",
	"holding_wt_upper":"0.2"
	}],
	"Fully invested": [{
	"fully_invested_lower":"0.04",
	"fully_invested_upper":"0.25"
	}]
}

This should only happen when the user clicks on Submit button.
Thank you @Snizl!

Well, I think the problem has 2 parts. One is making all relevant inputs accessible in your callback() and then taking those inputs to create your ideal JSON. @Snizl is right in where you reference all your data points with your State() attribute.

I assume you’ve looked at the Python JSON encoder (link below if needed), but that should give you enough info for the 2nd part of your problem.
https://docs.python.org/3/library/json.html