Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions fasthtml/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ def _fill_item(item, obj):
else: attr['value'] = val
if tag=='textarea': cs=(val,)
if tag == 'select':
for opt in cs:
if opt.tag == 'option': opt.attrs.pop('selected', None)
if isinstance(val, list):
for opt in cs:
if opt.tag == 'option' and opt.get('value') in val:
Expand Down
69 changes: 69 additions & 0 deletions nbs/api/01_components.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1020,6 +1020,8 @@
" else: attr['value'] = val\n",
" if tag=='textarea': cs=(val,)\n",
" if tag == 'select':\n",
" for opt in cs:\n",
" if opt.tag == 'option': opt.attrs.pop('selected', None)\n",
" if isinstance(val, list):\n",
" for opt in cs:\n",
" if opt.tag == 'option' and opt.get('value') in val:\n",
Expand Down Expand Up @@ -1128,6 +1130,73 @@
"multiform"
]
},
{
"cell_type": "markdown",
"id": "e75bc116",
"metadata": {},
"source": [
"Supplied select values replace existing selections, including defaults. An empty list clears them; missing or `None` values and controls with `skip` retain their selections."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2fd0d42a",
"metadata": {},
"outputs": [],
"source": [
"def selected_values(form): return lx.fromstring(to_xml(form)).xpath('//option[@selected]/@value')\n",
"\n",
"test_eq(selected_values(multiform), ['a', 'c'])\n",
"multiform = fill_form(multiform, {'items': ['b']})\n",
"test_eq(selected_values(multiform), ['b'])\n",
"multiform = fill_form(multiform, {'items': []})\n",
"test_eq(selected_values(multiform), [])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d815c231",
"metadata": {},
"outputs": [],
"source": [
"def default_select(**kw):\n",
" return Form(Select(Option('a', value='a', selected=True, data_foo='bar'), Option('b', value='b'), name='items', **kw))\n",
"\n",
"for val,expected in [(['b'], ['b']), ([], []), ('b', ['b']), ('missing', [])]:\n",
" filled = fill_form(default_select(multiple=True), {'items': val})\n",
" test_eq(selected_values(filled), expected)\n",
" test_eq(lx.fromstring(to_xml(filled)).xpath('//option[@value=\"a\"]/@data-foo'), ['bar'])\n",
"for obj in ({}, {'items': None}): test_eq(selected_values(fill_form(default_select(), obj)), ['a'])\n",
"test_eq(selected_values(fill_form(default_select(skip=True), {'items': ['b']})), ['a'])\n",
"\n",
"scalarform = Form(Select(Option('a', value='a', selected=True), Option('first b', value='b'),\n",
" Option('second b', value='b', selected=True), name='items'))\n",
"scalarform = fill_form(scalarform, {'items': 'b'})\n",
"test_eq(lx.fromstring(to_xml(scalarform)).xpath('//option[@selected]/text()'), ['first b'])\n",
"test_eq(selected_values(fill_form(scalarform, {'items': 'missing'})), [])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3179b5ef",
"metadata": {},
"outputs": [],
"source": [
"controls = Form(Input(type='checkbox', name='checks', value='a', checked=True),\n",
" Input(type='checkbox', name='checks', value='b'),\n",
" Input(type='radio', name='radio', value='a', checked=True), Input(type='radio', name='radio', value='b'),\n",
" Input(name='title', value='old', data_foo='bar'), Textarea('old', name='details'))\n",
"controls = fill_form(controls, {'checks': ['b'], 'radio': 'b', 'title': 'new', 'details': 'new details'})\n",
"controls = lx.fromstring(to_xml(controls))\n",
"test_eq(controls.xpath('//input[@checked]/@value'), ['b', 'b'])\n",
"test_eq(controls.xpath('//input[@name=\"title\"]/@value'), ['new'])\n",
"test_eq(controls.xpath('//input[@name=\"title\"]/@data-foo'), ['bar'])\n",
"test_eq(controls.xpath('//textarea/text()'), ['new details'])"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down