Callback that processes multiple inputs AND an editable DataTable

Hi All

I am new to dash so please forgive me if this has been addressed. Browsing/Searching through the forum did not reveal anything.
I have an app with the following basic workflow:
Input data for an ML model is entered/edited in four different “sections” (implemented using a tabbed user interface). One of these sections is an editable DataTable while the other three contain a mixture of dropdown/input/checkbox etc inputs. Other than the DataTable I don’t really need to have immediate callbacks for the inputs. Once the user has completed all four tabs and clicks on a simulated “submit” button I need a callback which includes the final values from all four tabs, including the entire DataTable and finally renders some output including charts. (The last part i.e. the output and rendering is easy, the part I am having difficulty with is callback input that includes a mixture of DataTables and inputs) I have seen callback examples that can process multiple inputs but none that can do a mixture of datatables and inputs.
Is this even possible?

Thank you.

A data table is not any different from other inputs. Could you post some code to illustrate the problem?

Hi, thanks for your quick reply. I had to strip out most of the code to make it executable as a standalone. (Backend databases, sklearn models etc).
I am stuck on the callback. I only need it to fire once the “submit” button is clicked. You will see that the call back happens immediately and currently only has the submit button in it.

import dash                                                           
from dash.dependencies import Input, Output                           
import dash_table                                                     
import dash_core_components as dcc                                    
import dash_html_components as html                                   
import pandas as pd                                                   
                                                                      
app = dash.Dash(__name__)                                             
                                                                      
                                                                      
params = [                                                            
    'Material', 'Percentage'                                          
]                                                                     
                                                                      
                                                                      
table = dash_table.DataTable(                                         
    id='materials-table',                                             
    columns = (                                                       
        [{'id': p, 'name': p} for p in params]                        
    ),                                                                
    data = [                                                          
        {'Material': 'Glyserol', 'Percentage': 10},                   
        {'Material': 'Elderberry Extract', 'Percentage': 20}          
    ],                                                                
    editable = True                                                   
)                                                                     
                                                                      
                                                                      
attributes = [                                                        
    html.Label('Health Benefit'),                                     
    dcc.Input(id='health-benefit', type='text')                       
]                                                                     
                                                                      
                                                                      
diet_suitability = [                                                  
    html.Label('Diet Suitability'),                                   
    dcc.Input(id='diet-suitability', type='text')                     
]                                                                     


certifications = [                                                    
    html.Label('Certifications'),                                     
    dcc.Input(id='certifications', type='text')                       
]                                                                     
                                                                      
                                                                      
submit_button = [                                                     
    html.Button('Submit', id='submit-button', value='Submit'),        
]                                                                     
                                                                      
                                                                      
model_output = [                                                      
    html.Div('Model Output Placeholder', id='model-output')           
]                                                                     
                                                                      
                                                                      
app.layout = html.Div([                                               
    table,                                                            
    html.Div(attributes),                                             
    html.Div(diet_suitability),                                       
    html.Div(certifications),                                         
    html.Div(submit_button),                                          
    html.Div(model_output)                                            
])                                                                    
                                                                      
                                                                      
@app.callback(                                                        
    Output('model-output', 'children'),                               
    Input('submit-button', 'n_clicks'))                               
def generate_model_output(n_clicks):                                                                       
    # This is where the code to                                       
    # process all the inputs will                                     
    # go so it needs access to ALL                                    
    # the data from the 4 tabs                                        
    return 'Model output'                                             
                                                                      
                                                                      
if __name__ == '__main__':                                            
    app.run_server(debug=True)

To prevent the initial fire, you can set prevent_initial_call=True. To make the properties of the other components available, you can add them as State. Hence the callback would be something like,

@app.callback(Output('model-output', 'children'), Input('submit-button', 'n_clicks'), [State('materials-table', 'data'), State('health-benefit', 'value'), ...], prevent_initial_call=True)
def generate_model_output(n_clicks, table_data, health_benefit, ...):
    return "Model output"

Thank you Emil, that is exactly what I needed.
I have pasted the final solution here for anyone else interested. (It is actually quite similar to the “Dash App With State” example in the documentation on callbacks.

import dash                                                           
from dash.dependencies import Input, Output, State                    
import dash_table                                                     
import dash_core_components as dcc                                    
import dash_html_components as html                                   
                                                                      
                                                                      
app = dash.Dash(__name__)                                             
                                                                      
                                                                      
params = [                                                            
    'Material', 'Percentage'                                          
]                                                                     
                                                                      
                                                                      
table = dash_table.DataTable(                                         
    id='materials-table',                                             
    columns = (                                                       
        [{'id': p, 'name': p} for p in params]                        
    ),                                                                
    data = [                                                          
        {'Material': 'Glyserol', 'Percentage': 10},                   
        {'Material': 'Elderberry Extract', 'Percentage': 20}          
    ],                                                                
    editable = True                                                   
)                                                                     
                                                                      
                                                                      
attributes = [                                                        
    html.Label('Health Benefit'),                                     
    dcc.Input(                                                        
        id='health-benefit',                                          
        type='text',                                                  
        value='Initial Health Benefit Value'                          
    )                                                                 
]                                                                     
                                                                      
                                                                      
diet_suitability = [                                                  
    html.Label('Diet Suitability'),                                   
    dcc.Input(                                                        
        id='diet-suitability',
        type='text',                                                  
        value='Initial DS Value'                                      
    )                                                                 
]                                                                     
                                                                      
                                                                      
certifications = [                                                    
    html.Label('Certifications'),                                    
    dcc.Input(                                                        
        id='certifications',                                          
        type='text',                                                  
        value='Initial Certifications'                                
    )                                                                 
]                                                                     
                                                                      
                                                                      
submit_button = [                                                    
    html.Button(                                                      
        id='submit-button',                                          
        children='Submit',                                            
        n_clicks=0,                                                   
    ),                                                                
]                                                                     
                                                                      
                                                                      
model_output = [                                                      
    html.Div('Model Output Placeholder', id='model-output')           
]                                                                     
                                                                      
                                                                      
app.layout = html.Div([                                               
    table,                                                            
    html.Div(attributes),                                             
    html.Div(diet_suitability),                                       
    html.Div(certifications),                                         
    html.Div(submit_button),                                          
    html.Div(model_output)                                            
])                                                                    
                                                                      

@app.callback(                                                        
    Output('model-output', 'children'),                               
    Input('submit-button', 'n_clicks'),                               
    State('materials-table', 'data'),                                 
    State('health-benefit', 'value'),                                 
    State('diet-suitability', 'value'),                               
    State('certifications', 'value'),                                 
    prevent_initial_call=True)                                        
def generate_model_output(n_clicks, materials_table_data,             
                          health_benefit_value,                       
                          diet_suitability_value,                     
                          certifications_value):                      
    # This is where the code to                                       
    # process all the inputs will                                     
    # go so it needs access to ALL                                    
    # the data from the 4 tabs                                        
    return 'Model output'                                             
                                                                      
                                                                      
if __name__ == '__main__':                                            |
    app.run_server(debug=True)