Brian
Brian
SSolara
Created by Brian on 2/20/2025 in #questions-issues
InputDate with buttons
with a fix to be released in Solara 2.0 (hopefully the coming week)
Exciting! 😄
12 replies
SSolara
Created by Brian on 2/20/2025 in #questions-issues
InputDate with buttons
Hi @iisakkirotko, thanks for your reply! I don't see how to use only one reactive variable to keep the date picker open. It seems like the open_value parameter is supposed to let me control the state of the menu, but within the InputDate component, it is directly calling datepicker_is_open.set(False) during the set_date_cast() method, which is called whenever the input variable changes -- i.e., when a user clicks on a date. So what I was seeing is: even though I am trying to control the open/closed state of the menu, it is being closed whenever a date is clicked on. (It seems like that might be a bug? If the user supplies a value for open_value, then set_date_cast() should probably not close the menu when a date is clicked on.)
12 replies
SSolara
Created by Brian on 2/20/2025 in #questions-issues
InputDate with buttons
If there's a cleaner way to do that, I'd be happy to hear it 😅.
12 replies
SSolara
Created by Brian on 2/20/2025 in #questions-issues
InputDate with buttons
Essentially, I'm tracking two additional reactive variables for the "true" state, and re-opening the menu if it was not closed by the user clicking one of the buttons.
12 replies
SSolara
Created by Brian on 2/20/2025 in #questions-issues
InputDate with buttons
I'm able to achieve the desired behavior by doing the following -- although I do think this is a bit of a hack.
import solara
import solara.lab
import datetime as dt


@solara.component
def Page():
# reactive variables to capture the "true" state
selected_date = solara.use_reactive(dt.date.today().replace(day=1))
selection_in_progress = solara.use_reactive(False)

# reactive variables that will be used by the existing InputDate component
date_picker_is_open = solara.use_reactive(False)
clicked_date = solara.use_reactive(dt.date.today().replace(day=1))

solara.use_memo(
lambda: clicked_date.set(selected_date.value),
[selected_date.value],
)

def on_open_value(is_open: bool) -> None:

if is_open:
selection_in_progress.set(True)

elif selection_in_progress.value:
date_picker_is_open.set(True)

def on_date_selected():
selected_date.set(clicked_date.value)
selection_in_progress.set(False)
date_picker_is_open.set(False)

def on_cancel():
clicked_date.set(selected_date.value)
selection_in_progress.set(False)
date_picker_is_open.set(False)

with solara.Column(style="width: 400px;"):
with solara.lab.InputDate(
clicked_date,
open_value=date_picker_is_open,
on_open_value=on_open_value,
date_picker_type="month",
date_format="%b %Y",
):
with solara.Row(justify="end", style="width: 100%;"):
solara.Button(
label="Cancel",
on_click=on_cancel,
text=True,
)
solara.Button(
label="Select",
color="primary",
on_click=on_date_selected,
)

Page()
import solara
import solara.lab
import datetime as dt


@solara.component
def Page():
# reactive variables to capture the "true" state
selected_date = solara.use_reactive(dt.date.today().replace(day=1))
selection_in_progress = solara.use_reactive(False)

# reactive variables that will be used by the existing InputDate component
date_picker_is_open = solara.use_reactive(False)
clicked_date = solara.use_reactive(dt.date.today().replace(day=1))

solara.use_memo(
lambda: clicked_date.set(selected_date.value),
[selected_date.value],
)

def on_open_value(is_open: bool) -> None:

if is_open:
selection_in_progress.set(True)

elif selection_in_progress.value:
date_picker_is_open.set(True)

def on_date_selected():
selected_date.set(clicked_date.value)
selection_in_progress.set(False)
date_picker_is_open.set(False)

def on_cancel():
clicked_date.set(selected_date.value)
selection_in_progress.set(False)
date_picker_is_open.set(False)

with solara.Column(style="width: 400px;"):
with solara.lab.InputDate(
clicked_date,
open_value=date_picker_is_open,
on_open_value=on_open_value,
date_picker_type="month",
date_format="%b %Y",
):
with solara.Row(justify="end", style="width: 100%;"):
solara.Button(
label="Cancel",
on_click=on_cancel,
text=True,
)
solara.Button(
label="Select",
color="primary",
on_click=on_date_selected,
)

Page()
12 replies
SSolara
Created by Brian on 2/20/2025 in #questions-issues
InputDate with buttons
Looking at the source code, when you pick a date, on_v_model calls a helper function for casting the date value properly: https://github.com/widgetti/solara/blob/master/solara/lab/components/input_date.py#L157 And that function is closing the datepicker: https://github.com/widgetti/solara/blob/master/solara/lab/components/input_date.py#L120 Since those things are buried inside the implementation of InputDate, I can't control them. 😕
12 replies
SSolara
Created by Brian on 11/20/2024 in #questions-issues
Localization of datetime
Hey @iisakkirotko thanks for the suggestion, I'll look into it a bit later! The date/time I have will be in UTC and it could be any date/time -- say the user saved some record two days ago -- and I want to display that date/time to the user in their timezone and locale. So it's not the current server time nor the current client's time. If I can get the client's timezone (the current time would be fine for that) somehow, then I would know how much to shift the date/time. And then I could get the locale from the headers.
4 replies
SSolara
Created by Brian on 11/20/2024 in #questions-issues
Localization of datetime
I also thought about specifying the tag for my solara.Success component -- hoping that I might be able to write a script to find that element and then modify the content -- but it doesn't seem like the tag gets applied to any of the HTML elements related to the component. Like:
solara.Success(
f"Saved at {some_datetime}",
tag="success-saved-at",
)
solara.Success(
f"Saved at {some_datetime}",
tag="success-saved-at",
)
4 replies
SSolara
Created by Brian on 8/5/2024 in #questions-issues
Creating a form when I don't know how many user inputs there will be at development time
Thank you for this example -- I was able to get it working by following what you did. Very helpful!
9 replies
SSolara
Created by Brian on 8/5/2024 in #questions-issues
Creating a form when I don't know how many user inputs there will be at development time
@solara.component
def Page():
def save_answers(answers):
print(f"Method to save answers to the database: {answers}")

bridge_of_death_is_open = solara.use_reactive(False)

with solara.Card(
"Who would cross the Bridge of Death must answer me "
"these questions three, ere the other side ye see:"
):
BridgeOfDeath(
bridge_of_death_is_open,
on_ok=save_answers,
questions=questions,
)

solara.Button(
label="Ask me the questions, I am not afraid.",
on_click=lambda: bridge_of_death_is_open.set(True),
)

Page()
@solara.component
def Page():
def save_answers(answers):
print(f"Method to save answers to the database: {answers}")

bridge_of_death_is_open = solara.use_reactive(False)

with solara.Card(
"Who would cross the Bridge of Death must answer me "
"these questions three, ere the other side ye see:"
):
BridgeOfDeath(
bridge_of_death_is_open,
on_ok=save_answers,
questions=questions,
)

solara.Button(
label="Ask me the questions, I am not afraid.",
on_click=lambda: bridge_of_death_is_open.set(True),
)

Page()
9 replies
SSolara
Created by Brian on 8/5/2024 in #questions-issues
Creating a form when I don't know how many user inputs there will be at development time
@solara.component
def BridgeOfDeath(is_open, on_ok, questions):
# normally, I would create some reactive variables here, but I don't know
# how many (apart from `len(questions)`). I also need to associate those
# reactive variables with to the question IDs so that I can save the data.

# Should it be a reactive dict, like:
# answers_by_question_id = solara.use_reactive({})

# Or a dict of reactive variables like:
answers_by_question_id = {
question["question_id"]: solara.use_reactive("")
for question in questions
}

def _on_ok():
print("_on_ok called")
on_ok(answers_by_question_id)

with solara.lab.ConfirmationDialog(
is_open,
ok=solara.Button(
label="Answer",
on_click=_on_ok,
# disabled= # if any question is unanswered
),
on_ok=_on_ok,
title="Answer",
max_width=1000,
):

for question in questions:
question_id = question["question_id"]
question_text = question["question_text"]

with solara.Card():
solara.Text(question_text)
solara.v.Spacer()
solara.InputText(
label=f"Question #{question_id}",
value=answers_by_question_id[question_id].value,
on_value=answers_by_question_id[question_id].set,
continuous_update=True,
)
@solara.component
def BridgeOfDeath(is_open, on_ok, questions):
# normally, I would create some reactive variables here, but I don't know
# how many (apart from `len(questions)`). I also need to associate those
# reactive variables with to the question IDs so that I can save the data.

# Should it be a reactive dict, like:
# answers_by_question_id = solara.use_reactive({})

# Or a dict of reactive variables like:
answers_by_question_id = {
question["question_id"]: solara.use_reactive("")
for question in questions
}

def _on_ok():
print("_on_ok called")
on_ok(answers_by_question_id)

with solara.lab.ConfirmationDialog(
is_open,
ok=solara.Button(
label="Answer",
on_click=_on_ok,
# disabled= # if any question is unanswered
),
on_ok=_on_ok,
title="Answer",
max_width=1000,
):

for question in questions:
question_id = question["question_id"]
question_text = question["question_text"]

with solara.Card():
solara.Text(question_text)
solara.v.Spacer()
solara.InputText(
label=f"Question #{question_id}",
value=answers_by_question_id[question_id].value,
on_value=answers_by_question_id[question_id].set,
continuous_update=True,
)
9 replies
SSolara
Created by Brian on 8/5/2024 in #questions-issues
Creating a form when I don't know how many user inputs there will be at development time
import pandas as pd
import solara

# assume that we have a table in a database, and
# we read the data into _something_ like this:
#
question_table = pd.DataFrame(
data=[
[1, "What is your name?"],
[2, "What is your quest?"],
[3, "What is your favorite color?"]
],
columns=["question_id", "question_text"]
)

# or else it can be treated like a list of dicts
#
questions = question_table.to_dict(orient="records")
# questions
# [{'question_id': 1, 'question_text': 'What is your name?'},
# {'question_id': 2, 'question_text': 'What is your quest?'},
# {'question_id': 3, 'question_text': 'What is your favorite color?'}]
import pandas as pd
import solara

# assume that we have a table in a database, and
# we read the data into _something_ like this:
#
question_table = pd.DataFrame(
data=[
[1, "What is your name?"],
[2, "What is your quest?"],
[3, "What is your favorite color?"]
],
columns=["question_id", "question_text"]
)

# or else it can be treated like a list of dicts
#
questions = question_table.to_dict(orient="records")
# questions
# [{'question_id': 1, 'question_text': 'What is your name?'},
# {'question_id': 2, 'question_text': 'What is your quest?'},
# {'question_id': 3, 'question_text': 'What is your favorite color?'}]
9 replies
SSolara
Created by Brian on 8/5/2024 in #questions-issues
Creating a form when I don't know how many user inputs there will be at development time
My issue/question is: how do I create the reactive variable(s) to capture the user input? I would expect that the value that I want to pass to the InputText should be a reactive variable (?), or else that I would create a reactive variable that is a dictionary and have it be keyed by question_id with the values being the text in the InputText. I've tried creating a dict of reactive variables and a reactive dict, but it doesn't seem to work. Here is a minimal example. It "works," except that when you click "Answer" nothing happens -- the print statements do not execute.
9 replies
SSolara
Created by Brian on 8/5/2024 in #questions-issues
Creating a form when I don't know how many user inputs there will be at development time
I want to create a form that has a few questions for a user to answer. I want to store the questions in a database, which means that the application won't know ahead of time how many questions there will be. So let's say a have a table like:
| question_id | question_text |
|-------------|------------------------------|
| 1 | What is your name? |
| 2 | What is your quest? |
| 3 | What is your favorite color? |
| question_id | question_text |
|-------------|------------------------------|
| 1 | What is your name? |
| 2 | What is your quest? |
| 3 | What is your favorite color? |
On application start, I would expect to read these questions into a dictionary {question_id: question_text}. When constructing my form (using solara.lab.ConfirmationDialog), I would loop through the list of questions to create a prompt (solara.Text) and an input text box (solara.InputText). When the user submits the form, I want to capture the responses and write them to a table in my database like:
| submission_id | answer_id | question_id | answer_text |
|---------------|-----------|-------------|-----------------------|
| 1 | 1 | 1 | Sir Lancelot |
| 1 | 2 | 2 | I seek the Holy Grail |
| 1 | 3 | 3 | Blue |
| 2 | 4 | 1 | Sir Galahad |
| 2 | 5 | 2 | I seek the Grail |
| 2 | 6 | 3 | Blue... |
| submission_id | answer_id | question_id | answer_text |
|---------------|-----------|-------------|-----------------------|
| 1 | 1 | 1 | Sir Lancelot |
| 1 | 2 | 2 | I seek the Holy Grail |
| 1 | 3 | 3 | Blue |
| 2 | 4 | 1 | Sir Galahad |
| 2 | 5 | 2 | I seek the Grail |
| 2 | 6 | 3 | Blue... |
9 replies
SSolara
Created by Brian on 8/5/2024 in #questions-issues
Creating a form when I don't know how many user inputs there will be at development time
Sorry for the bad formatting... Discord won't let me paste text without adding it as an attachment.
9 replies
SSolara
Created by Brian on 4/18/2024 in #questions-issues
PermissionError for nbextensions on startup with v1.29+
i think i have resolved my issue -- by chmod-ing my /usr/local/share directory to allow more access than was initially present. however, i mentioned in the issue that i raised that the path that was causing trouble did not even exist. so i wonder if the code could be improved by catching PermissionErrors -- if the user doesn't have permission to the directory or file, that is basically the same as "does not exist".
9 replies
SSolara
Created by Brian on 4/18/2024 in #questions-issues
PermissionError for nbextensions on startup with v1.29+
I just created this issue for this.
9 replies
SSolara
Created by Brian on 4/18/2024 in #questions-issues
PermissionError for nbextensions on startup with v1.29+
i think maybe this change is the culprit.
9 replies
SSolara
Created by Brian on 4/18/2024 in #questions-issues
PermissionError for nbextensions on startup with v1.29+
i can create an issue in GitHub if that's more appropriate.
9 replies
SSolara
Created by Brian on 4/18/2024 in #questions-issues
PermissionError for nbextensions on startup with v1.29+
the logging output with stacktrace is:
9 replies