Search code examples
pythonfirebasekivykivy-languagekivymd

Pass dynamically created button information to a function when they are pressed. kivymd, kivy, python


I am trying to delete information about the button when the user presses the trash can on the button.

My problem is that when the user presses the trash can of any button, only the information of the button that is lastly created gets passed to the function, and therefore only the last created button get deleted instead of the one of the button that is pressed.

Please see the picture below.

picture

        docs = users_ref.collection(u'Education').stream()
        education_lst = []
        education_btn = []

        for doc in docs:
            dict = doc.to_dict()
            education_lst.append(dict['Graduation'])
            primary = str(dict['University'])
            secondary = str(dict['Degree']) + ' in ' + str(dict['Major'])
            tertiary = 'Graduation year: ' + dict['Graduation']

            btn = ThreeLineAvatarIconListItem(text=primary, secondary_text=secondary, tertiary_text=tertiary)
            education_btn.append(btn)
        for btn in education_btn:
            pic = IconRightWidget(icon='trash-can')
            pic.bind(on_release=lambda *args: Education().delete(education_lst[education_btn.index(btn)]))
            btn.add_widget(pic)
            sm.get_screen('profile').ids.profile_grid.add_widget(btn)

Solution

  • That's a common problem when defining a lambda function in a loop. The loop variable used in the lambda function isn't evaluated until the lambda is actually executed. So, in your case, the btn argument ends up being the last value of btn. A fix is to use a new variable to hold the value of the loop variable, like this:

    pic.bind(on_release=lambda *args, x=btn: self.delete(education_lst[education_btn.index(x)]))