How to render an ui element with background task? #3170
-
QuestionI'm creating a chat component to communicate with a llm agent. I used the examples in the nicegui page but I must to be able to render plots and tables in the chat. I created the chat component like this: from nicegui import ui, run
messages: list[tuple[str, bool, ui.element | None]] = [
("Hi, I'm a bot", False, None)
]
@ui.refreshable
def chat_messages():
"""Chat history"""
for message, sent, avatar, element in messages:
with ui.chat_message(sent=sent, avatar=avatar).style(
'margin-right: 10px;'
):
ui.label(message)
if element: # here is where must to render the element
element
@ui.page('/')
def chat(client):
async def send():
if text.value:
messages.append((text.value, True, None))
chat_messages.refresh()
await run.io_bound(response)
def response():
"""Get llm response"""
temp = text.value
text.value = ''
spinner.set_visibility(True)
label_response = (1, 'Hi')
messages.append((
label_response[1],
False,
ui.button('asa') # An example with the element to render
))
spinner.set_visibility(False)
chat_messages.refresh()
with ui.element('q-fab'):
with ui.element('div'):
with ui.element('nav'):
with ui.element('div'):
ui.label('ChatBot Name')
with ui.element('div'):
chat_messages()
spinner = ui.spinner(type='dots')
spinner.set_visibility(False)
with ui.element('div'):
text = ui.input(label='digite uma mensagem').on('keydown.enter', send)
ui.button(icon='send', on_click=lambda: send)
ui.run() I hided the classes and props to make the script more readable. Running with this script I have the error:
How can I fix this? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 6 replies
-
Creating ui elements in the background needs to be below the element container that has already been created. For example: with ui.element('div') as mydiv:
pass
def yourbackgroundtest():
with mydiv:
newelement |
Beta Was this translation helpful? Give feedback.
-
Your code is not executable. Could you please provide a minimal, executable code snippet reproducing the problem. This will allow the community and us to identify and fix it more efficiently. |
Beta Was this translation helpful? Give feedback.
-
I'm struggling to get your example working. I think it needs some cleanup before we can tackle the actual problem. E.g. right now everything is nested under a floating action button, which is pretty strange. And try to remove unnecessary things like the spinner while keeping the things that matter. In general I would recommend not to create the UI within the async def send():
if text.value:
messages.append((text.value, True, None))
chat_messages.refresh()
message = await run.io_bound(response)
messages.append((message, False, ui.button('asa')))
spinner.set_visibility(False)
chat_messages.refresh() |
Beta Was this translation helpful? Give feedback.
I'm struggling to get your example working. I think it needs some cleanup before we can tackle the actual problem. E.g. right now everything is nested under a floating action button, which is pretty strange. And try to remove unnecessary things like the spinner while keeping the things that matter.
In general I would recommend not to create the UI within the
response()
function. Let it return the data and build the UI after awaiting it: