How to make streamlit widgets that interact with each other to store previous input?

Viewed 359

I'm trying to make a page in streamlit where I have two multiselect widgets to select between states and cities.

First the user need to choose the State, then only the cities that belong to that state will appear in the selection. So far, so good.

The problem starts when I have already selected some cities, but then I try to choose another state. When I do that, my cities widget is wiped clean and then I have to choose all the cities again.

Cities for AM state

User can choose the city

When the user chooses another states, the city widget resets

When another state is chosen, the city widget resets

Now I can choose between all the cities from the states chosen

for uf, cidade, ciclo in lista_cidades:
            if uf in uf_dict:
                uf_dict[uf].append(cidade)
            else:
                uf_dict[uf]=[cidade]
                
        st.multiselect('Selecione o estado', sorted(uf_dict), key='UF')

        for uf in st.session_state.UF:
            for city in uf_dict[uf]:
                city_list.append(city)

        st.multiselect('Selecione a cidade', sorted(city_list), key='cities')

        for city in st.session_state.cities:
            for k, v in uf_dict.items():
                if city in v:
                    st.session_state.cities_selected.append((k, city))

The uf_dict variable looks like this

uf_dict = {
  "AM": [
    "MANAUS",
    "ITACOATIARA"
  ],
  "GO": [
    "JATAI",
    "MINEIROS",
    "FORMOSA",
    "INHUMAS",
    "ITABERAÍ",
    "JARAGUÁ"
  ]
}

Is there a way where I can save the previously selected cities, so I don't need to choose all over again?

1 Answers

I actually managed to find a solution.

First I created this callback function:

def callback(state, object):
    st.session_state[f'{state}'] = object

Then I used this code:

    if (
        st.button('EXECUTE', on_click=callback, args=('execute', True))
        or st.session_state.execute == True
    ):
        st.warning('Are you sure you want to execute this?')
        if st.button('YES'):
            st.write('You did it!')

When I click the 'EXECUTE' button, I call the callback function and then I can execute another command.

This is the result:

Step 1

Step 2

Step 3

Related