文章目录
前言
近期一个项目中,使用streamlit作为用户交互的UI,要求能够使用扫码枪输入编码,使用了text input组件,但运行时发现默认的焦点并不在text input上,需要鼠标点击一下才行,操作不友好,找了不少资料后,终于解决,做下记录。
首先通过搜索工具,查到最接近的帖子如下
使用如下代码
import streamlit.components.v1 as components
import streamlit as st
def cbk():
st.session_state['delete_line'] = True
# st.session_state['counter'] += 1
option = st.selectbox('', [1,2,3],
index=1,
key='id_combo',
on_change=cbk)
if 'delete_line' not in st.session_state:
st.session_state['delete_line'] = True
if 'counter' not in st.session_state:
st.session_state['counter'] = 0
if st.session_state['delete_line']:
st.session_state['id_answer'] = ''
st.session_state['delete_line'] = False
y = st.text_input(f'', key='id_answer', on_change=cbk)
components.html(
f"""
<div>some hidden container</div>
<p>{st.session_state.counter}</p>
<script>
var input = window.parent.document.querySelectorAll("input[type=text]");
for (var i = 0; i < input.length; ++i) {{
input[i].focus();
}}
</script>
""",
height=150
)
st.write(f'the submitted answer was {y}')
if st.button('Check', on_click=cbk):
st.session_state['delete_line'] = True
其中关键的是JavaScript的这段
input = window.parent.document.querySelectorAll("input[type=text]");
input[i].focus();
也就是获取所有的输入组件,并将焦点固定到最后一个输入框。
写了个测试代码进行调试,该方法可行
import streamlit as st
import streamlit.components.v1 as components
st.text_input(label='电池编号:')
st.text_input('电池型号:')
components.html(
f"""
<script>
var allinputs = window.parent.document.querySelectorAll("input[type=text]");
allinputs[0].focus();
</script>
"""
)
即获取所有的输入组件,并将焦点放到第1个组件,但这样ui修改后,需要知道需要获取的焦点组件顺序才行,最好是能够通过组件的编号信息来设置。
对运行的网页进行查看,发现其有个 aria-label的属性,该属性就是我们在streamlit里设置的label值
故按如下修改JS的代码,便可通过label来设置焦点
import streamlit as st
import streamlit.components.v1 as components
st.text_input(label='电池编号:')
st.text_input(label='电池型号:')
components.html(
f"""
<script>
var batsn = window.parent.document.querySelector('[aria-label="电池编号:"]');
batsn.focus();
</script>
"""
)