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

Output from callback not going to layout

I’m having a problem with a system that I’m building. When the login screen is called and the person that logs in is a client, I want to create a dataframe with a datatable showing information on the screen. When I test the logic, I output the data to a PowerShell window with a print command so that I know that the logic is working and I have an output dataset. This tells me that the login callback is working and my logic is correct. For some reason the layout function with the datatable in it is not being called, nothing happens.

In the login layout function I have a silent div at the end. If I comment out the line of code, when I type in the email address and password for a client there’s no output from the print statement into the power shell window at the end of the login callback function. Can anyone tell me why?

The applicable code is as follows:

I took the code from dash bootstrap components simple sidebar for app.py. The following is just some of the applicable code:

column_names = []
df_portfolio = pd.DataFrame(columns = column_names)
callbacks.sample_portfolio(app, df_portfolio)

callbacks.login(app)
callbacks.open_account(app)
callbacks.contact_layout(app)

def render_page_content(pathname):
    if pathname in ['/', '/page-1']:
        return layout.welcome()
    elif pathname == "/page-2":
        return layout.login(app)
    elif pathname == "/page-3":
        return layout.open_account(app)
    elif pathname == "/page-4":
        return layout.sample_portfolio_layout(app, df_portfolio)
    elif pathname == "/page-5":
       return layout.contact_layout(app)
    elif pathname == '/page-6':
        return layout.faq()
    elif pathname == '/page-7':
        return layout.journal_data_entry(app, cust_info, ee_info, acct_info)

login layout function:

def login(app):
    return html.Div([
        html.Div(children = [
            html.Div( children = [
                html.Label('Email Address',
                    ),
                dcc.Input(type = 'email',
                    id = 'email', 
                    placeholder = 'email@example.com',
                    minLength = 7, 
                    maxLength = 40,
                    debounce = True,
                    className = 'form-control',
                ),  
                ], className = 'form-group'
            ),
            html.Div( children = [
                html.Label('Password:',
                    ),
                dcc.Input(type = 'password',
                    id = 'password', 
                    placeholder = 'Password',
                    minLength = 8, 
                    maxLength = 25,
                    debounce = True,
                    className = 'form-control'
                ),
            ], className = 'form-group'
            ),
            dbc.Button('Submit',
                id = 'login_submit',
                color = 'primary',
                className = 'mr-1',
                n_clicks = 0),
        ], 
        style = LOGIN_STYLE,
        ), 
    html.Div(id = 'record', style = {'display': 'none'}),
    ],
)

login callback function:

def login(app):
   @app.callback(
      Output('record', 'data'),
      [Input('login_submit', 'n_clicks'),
      Input('record', 'value')],
      [State('email', 'value'),
      State('password', 'value')]
   )
   def cl_login(n, cust_info, email, password):
      if n is None:
         return no_update

      def validate_data(email, password):
         # test to see if either login or password is blank
         if email is None or password is None:
            return False
         else:
            return True 

      # Check to make sure all required fields are entered 
      # (see def validate_data above)
      data_ok = validate_data(email, password)
      if not data_ok:
         return 'Your email address and password are required'

      # Data was entered into both the login and password fields. 
      # Check for record in Login table
      engine = create_engine('sqlite:///roboinvest.db')
      Base = declarative_base()
      conn = sqlite3.connect(reference.database)
      c = conn.cursor()

      '''Check login table to see if the record exists. If it exists, 
      see if it is for a (C)ustomer, (E)mployee or (A)dministrator'''
      c.execute(
         'SELECT \
            rec_type \
         FROM \
            Login \
         Where email = ? and Password = ?', \
         (email, password))

      try:
         rec_type = c.fetchall()[0][0]
      except:
         return 'There is no record for this email and password combination'

      if rec_type != 'C':
         return 'This id/password combination is not for a client'

      # Get customer data
      c.execute( \
         'SELECT DISTINCT\
            CASE \
               when customer_master.Middle_initial is Null \
               then customer_master.First_name || " " || customer_master.Last_name  \
               else customer_master.First_name || " " || customer_master.Middle_initial || " " || customer_master.Last_name \
            END name, \
            account_master.account_number, \
            account_master.account_balance, \
            journal_entries.date_of_entry, \
            journal_entries.transaction_type,\
            journal_entries.transaction_amount \
         FROM \
            customer_master \
            Inner join login On \
               login.id = customer_master.cust_id \
            Inner join account_master On \
               account_master.cust_id = customer_master.cust_Id \
            Inner join journal_entries On \
               journal_entries.cust_id = account_master.cust_id \
            Where \
               login.email = ? and login.password = ?', \
               (email, password))

      customer_information = []
      customer_information = c.fetchall()

      cust_info = []
      for count in range(len(customer_information)):
         cust_info += [[customer_information[count][0],
                        customer_information[count][1],
                        customer_information[count][2],
                        customer_information[count][3],
                        customer_information[count][4],
                        customer_information[count][5]]]
      
      # Create pandas dataframe
      cust_info = pd.DataFrame(cust_info, 
         columns = ['name', 'account number', 'account balance', 'date of entry', 
            'transaction type', 'transaction amount'])
      print('cust_info ', cust_info)
      return cust_info.to_dict('records')

The login callback function should call the following layout program that has the datatable in it but doesn’t seem to:

def present_customer_data_layout(app):
    return html.Div([
    html.Br(),
    html.Br(),
    html.H5('Client Information',
        style = TEXT_ALIGN_CENTER ),
    html.Br(),
    dash_table.DataTable(
        id='record',
        columns = [
            {'name': 'Customer Name', 
                'id' : 'name'},
            {'name': 'Account Number',
                'id': 'account number'},
            {'name': 'Account Balance', 
                'id' : 'account balance',
                'type' : 'numeric',
                'format': FormatTemplate.money(2)},
            {'name': 'Date of Transaction', 
                'id' : 'date of entry'},
            {'name': 'Transaction Type', 
                'id' : 'transaction type'},
            {'name': 'Transaction Amount', 
                'id' : 'transaction amount',
                'type' : 'numeric',
                'format': FormatTemplate.money(2)},
        ],
        style_header = {
            'backgroundColor': 'rgb(230,230,230)', 
            'font-weight' : 'bold',
        },
        style_cell = {
            'textAlign' : 'center'
        },
        style_data_conditional=
        [
            {'if': {'row_index': 'odd'}, 'backgroundColor': 'rgb(248, 248, 248)'},
        ],  
        style_table = {
            'maxHeight': '300px', 
            'overflowY' : 'scroll',
            'font-family': 'sans-serif',
            'font-size': '24',
        } 
    ),
    html.Div(id = 'customer_record')
])