Browse Source

fix value of ChoiceElements after changing options

Falko Schindler 1 year ago
parent
commit
50bec3a1d3
4 changed files with 45 additions and 0 deletions
  1. 3 0
      nicegui/elements/choice_element.py
  2. 16 0
      tests/test_radio.py
  3. 13 0
      tests/test_select.py
  4. 13 0
      tests/test_toggle.py

+ 3 - 0
nicegui/elements/choice_element.py

@@ -23,7 +23,10 @@ class ChoiceElement(ValueElement):
         self._labels = self.options if isinstance(self.options, list) else list(self.options.values())
 
     def _update_options(self) -> None:
+        before_value = self.value
         self._props['options'] = [{'value': index, 'label': option} for index, option in enumerate(self._labels)]
+        self._props[self.VALUE_PROP] = self._value_to_model_value(before_value)
+        self.value = before_value if before_value in self._values else None
 
     def update(self) -> None:
         self._update_values_and_labels()

+ 16 - 0
tests/test_radio.py

@@ -0,0 +1,16 @@
+from nicegui import ui
+
+from .screen import Screen
+
+
+def test_changing_options(screen: Screen):
+    r = ui.radio([10, 20, 30], value=10)
+    ui.label().bind_text_from(r, 'value', lambda v: f'value = {v}')
+    ui.button('reverse', on_click=lambda: (r.options.reverse(), r.update()))
+    ui.button('clear', on_click=lambda: (r.options.clear(), r.update()))
+
+    screen.open('/')
+    screen.click('reverse')
+    screen.should_contain('value = 10')
+    screen.click('clear')
+    screen.should_contain('value = None')

+ 13 - 0
tests/test_select.py

@@ -62,3 +62,16 @@ def test_multi_select(screen: Screen):
 
     screen.click('cancel')  # remove icon
     screen.should_contain("['Bob']")
+
+
+def test_changing_options(screen: Screen):
+    s = ui.select([10, 20, 30], value=10)
+    ui.label().bind_text_from(s, 'value', lambda v: f'value = {v}')
+    ui.button('reverse', on_click=lambda: (s.options.reverse(), s.update()))
+    ui.button('clear', on_click=lambda: (s.options.clear(), s.update()))
+
+    screen.open('/')
+    screen.click('reverse')
+    screen.should_contain('value = 10')
+    screen.click('clear')
+    screen.should_contain('value = None')

+ 13 - 0
tests/test_toggle.py

@@ -22,3 +22,16 @@ def test_adding_toggle_options(screen: Screen):
     screen.should_contain('D')
     screen.click('D')
     screen.should_contain('Choice: D')
+
+
+def test_changing_options(screen: Screen):
+    t = ui.toggle([10, 20, 30], value=10)
+    ui.label().bind_text_from(t, 'value', lambda v: f'value = {v}')
+    ui.button('reverse', on_click=lambda: (t.options.reverse(), t.update()))
+    ui.button('clear', on_click=lambda: (t.options.clear(), t.update()))
+
+    screen.open('/')
+    screen.click('reverse')
+    screen.should_contain('value = 10')
+    screen.click('clear')
+    screen.should_contain('value = None')