taipy
taipy copied to clipboard
How to bind indexed variables
Description
Check out this app where I generate selectors dynamically:
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)
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()
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.