Groups of radioboxes: Not all Python-Objects updated correctly?
See original GitHub issueI am currently implementing an interface where I want to place a group of radioboxes (<input type='radio' ...>
) where an user can select one-of-many.
I’ve started by copying the Checkbox
from lona.html.data_binding_inputs
to get the following:
class Radiobox(CheckBox):
INPUT_ATTRIBUTE_NAME = 'checked'
ATTRIBUTES = {
'type': 'radio',
}
def __init__(self, value=False, disabled=False, readonly=False,
bubble_up=False, **kwargs):
super().__init__(value, disabled, readonly, bubble_up, **kwargs)
if 'input_delay' not in kwargs:
self.events = [CHANGE]
@property
def value(self) -> bool:
value = self.attributes.get(self.INPUT_ATTRIBUTE_NAME, False)
if value == '': # is possible after parsing HTML string
return True
return bool(value)
@value.setter
def value(self, new_value: bool) -> None:
if not isinstance(new_value, bool):
raise TypeError('value is a boolean property')
self.attributes[self.INPUT_ATTRIBUTE_NAME] = new_value
Next step was to create a group of radioboxes
like this:
Div(
Radiobox(_id=1, name='groupname'),
Radiobox(_id=2, name='groupname', checked=True),
)
When toggling the radiobox in the frontend to the other one I end up with both nodes on the python-side having checked=True
.
It seems as the other Radiobox does not emit an input_event
to update it’s state.
On a high level I would expect both Radoboxes to update at the same time. What is the expected behavior here?
Workaround:
My plan was to have Radiogroup-Widget anyway. So I have a single object that I can query for the current value and that creates the Radioboxes and Labels by itself.
But since I can not rely on the .value
of the radio-boxes I am currently tracking the state of the group by hand. And this feels wrong.
Here is my prototype:
class Radiogroup(Widget):
def __init__(self, options, checked=None):
"""
Creates a Group of radiobuttons.
Arguments:
* options: Dict of options
{ 'id-name 1': 'Screen Name 1', ... }
* checked: String with the <id> of the pre-checked item
"""
self._mapping = {}
div = Div()
for ident, screenname in options.items():
rb = Radiobox(_id=ident, name=f'radiogroup-{self.id}', bubble_up=True)
if ident == checked:
rb.attributes['checked'] = 'True'
div.append(rb)
div.append(Label(screenname, _for=ident))
div.append(Br())
self._mapping[rb.id] = ident
self.nodes = [div]
self._value = checked
def handle_input_event(self, input_event):
self._value = self._mapping[input_event.node.id]
@property
def value(self):
return self._value
@value.setter
def value(self, new_value):
for node in self.query_selector_all('input'):
if self._mapping[node.id] == new_value:
node.value = True
else:
node.vale = False
direction = Radiogroup(
{
'received': 'Payment received',
'sent': 'Payment sent',
},
checked='received',
)
I would really like to see this Widget as part of Lona at some point. But I would like to clarify my understanding of the event-system before contributing any code 😃
Issue Analytics
- State:
- Created a year ago
- Comments:13 (13 by maintainers)
Top GitHub Comments
@SmithChart, @maratori: I implemented a solution that is a combination of my proposal and maratoris backend-side synchronization approach: The RadioButton it self is self-contained, but unchecks all surrounding RadioButtons when it gets checked. I did also build a RadioButtonGroup around RadioButtons that implements properties like
value
,values
andname
https://github.com/lona-web-org/lona/blob/fscherf/topic/radio-buttons/lona/html/data_binding/radio_buttons.py
This seems to be a very similar problem like #276. I will revisit this when when we decided on the select api