taipy icon indicating copy to clipboard operation
taipy copied to clipboard

How to bind indexed variables

Open AlexandreSajus opened this issue 1 year ago β€’ 1 comments

Description

Check out this app where I generate selectors dynamically: image

from taipy.gui import Gui
import taipy.gui.builder as tgb

questions = ["Are you alive ?", "aRe yOU sUre ?"]
answers = [""] * len(questions)


def selector(state):
    print(state.answers)


with tgb.Page() as page:
    for i, question in enumerate(questions):
        tgb.text(f"#### {question}", mode="md")
        tgb.selector(
            value="{answers[" + str(i) + "]}",
            lov=["Yes", "No"],
            on_change=selector,
        )


Gui(page).run()

How do I store the answers (the values selected)? Here, I try to store the answers in the answers list, but instead of assigning the selected value to answers[0], it assigns it to answers, so I lose the other answers.

Solution Proposed

There are multiple solutions but one should be implemented and documented:

  • We could let the user bind a selector to an element of a list like I tried to do above
  • We could let the user not bind the selector and define a var_name property. This way the user could store answers at the on_change(state, var_name, value) level

Currently, the workaround is using exec to create variables on the fly and it is not elegant:

def selector(state, var_name, value):
    index = int(var_name[10:])
    state.answers[index] = value
    state.answers = state.answers
    print(state.answers)


with tgb.Page() as page:
    for i, question in enumerate(questions):
        tgb.text(f"#### {question}", mode="md")
        exec(f"selection_{i} = ''")
        tgb.selector(
            value="{selection_" + str(i) + "}",
            lov=["Yes", "No"],
            on_change=selector,
        )

Impact of Solution

No response

Additional Context

No response

Acceptance Criteria

  • [ ] Ensure new code is unit tested, and check code coverage is at least 90%.
  • [ ] Create related issue in taipy-doc for documentation and Release Notes.
  • [ ] Check if a new demo could be provided based on this, or if legacy demos could be benefit from it.
  • [ ] Ensure any change is well documented.

Code of Conduct

  • [X] I have checked the existing issues.
  • [ ] I am willing to work on this issue (optional)

AlexandreSajus avatar Sep 13 '24 10:09 AlexandreSajus

Florian explained to me that binding to dictionaries does work, but this approach is not documented as far as I have seen:

from taipy.gui import Gui
import taipy.gui.builder as tgb

questions = ["Hello", "dqdqd"]
answers = {}

for i, question in enumerate(questions):
    answers[i] = ""


def selector(state, var_name, value):
    print(state.answers.Hello)


with tgb.Page() as page:
    for i, question in enumerate(questions):
        tgb.text(f"#### {question}", mode="md")
        tgb.selector(
            value="{answers." + question + "}",
            lov=["Yes", "No"],
            on_change=selector,
        )


Gui(page).run()

AlexandreSajus avatar Sep 13 '24 13:09 AlexandreSajus

Just to add a bit here:

This code is also valid:

from taipy.gui import Gui
import taipy.gui.builder as tgb

questions = ["Hello"]
answers = {}

def printer(state, var_name, value):
    print(state.answers.items())
    print(state.answers["Hello"])

with tgb.Page() as page:
    for question in questions:
        tgb.text(f"#### {question}", mode="md")
        tgb.selector(
            value="{answers." + question + "}",
            lov=["Yes", "No"],
            on_change=printer,
        )

Gui(page).run()

I'm not sure why the dictionary was enumerated in the previous example and this code demonstrates, that ["key"] can also be used to retrieve the variable. The access of the dictionary with .key in the value string, instead of ["key"] is a bit unpythonic, but cool that it its possible.

JosuaCarl avatar Jan 13 '25 10:01 JosuaCarl