浏览代码

Merge pull request #1952 from groucho86/patch-1

integer argument for ui.number
Falko Schindler 1 年之前
父节点
当前提交
16ae12dac6
共有 3 个文件被更改,包括 46 次插入1 次删除
  1. 15 0
      nicegui/elements/number.py
  2. 20 0
      tests/test_number.py
  3. 11 1
      website/more_documentation/number_documentation.py

+ 15 - 0
nicegui/elements/number.py

@@ -14,6 +14,7 @@ class Number(ValidationElement, DisableableElement):
                  value: Optional[float] = None,
                  min: Optional[float] = None,  # pylint: disable=redefined-builtin
                  max: Optional[float] = None,  # pylint: disable=redefined-builtin
+                 precision: Optional[int] = None,
                  step: Optional[float] = None,
                  prefix: Optional[str] = None,
                  suffix: Optional[str] = None,
@@ -33,6 +34,7 @@ class Number(ValidationElement, DisableableElement):
         :param value: the initial value of the field
         :param min: the minimum value allowed
         :param max: the maximum value allowed
+        :param precision: the number of decimal places allowed (default: no limit, negative: decimal places before the dot)
         :param step: the step size for the stepper buttons
         :param prefix: a prefix to prepend to the displayed value
         :param suffix: a suffix to append to the displayed value
@@ -51,6 +53,7 @@ class Number(ValidationElement, DisableableElement):
             self._props['min'] = min
         if max is not None:
             self._props['max'] = max
+        self._precision = precision
         if step is not None:
             self._props['step'] = step
         if prefix is not None:
@@ -79,6 +82,16 @@ class Number(ValidationElement, DisableableElement):
         self._props['max'] = value
         self.sanitize()
 
+    @property
+    def precision(self) -> Optional[int]:
+        """The number of decimal places allowed (default: no limit, negative: decimal places before the dot)."""
+        return self._precision
+
+    @precision.setter
+    def precision(self, value: Optional[int]) -> None:
+        self._precision = value
+        self.sanitize()
+
     @property
     def out_of_limits(self) -> bool:
         """Whether the current value is out of the allowed limits."""
@@ -91,6 +104,8 @@ class Number(ValidationElement, DisableableElement):
         value = float(self.value)
         value = max(value, self.min)
         value = min(value, self.max)
+        if self.precision is not None:
+            value = float(round(value, self.precision))
         self.set_value(float(self.format % value) if self.format else value)
 
     def _event_args_to_value(self, e: GenericEventArguments) -> Any:

+ 20 - 0
tests/test_number.py

@@ -1,3 +1,4 @@
+import pytest
 from selenium.webdriver.common.by import By
 
 from nicegui import ui
@@ -56,3 +57,22 @@ def test_out_of_limits(screen: Screen):
 
     number.max = 15
     screen.should_contain('out_of_limits: False')
+
+
+@pytest.mark.parametrize('precision', [None, 1, -1])
+def test_rounding(precision: int, screen: Screen):
+    number = ui.number('Number', value=12, precision=precision)
+    ui.label().bind_text_from(number, 'value', lambda value: f'number=_{value}_')
+
+    screen.open('/')
+    screen.should_contain('number=_12_')
+
+    element = screen.selenium.find_element(By.XPATH, '//*[@aria-label="Number"]')
+    element.send_keys('.345')
+    screen.click('number=')  # blur the number input
+    if precision is None:
+        screen.should_contain('number=_12.345_')
+    elif precision == 1:
+        screen.should_contain('number=_12.3_')
+    elif precision == -1:
+        screen.should_contain('number=_10.0_')

+ 11 - 1
website/more_documentation/number_documentation.py

@@ -10,10 +10,20 @@ def main_demo() -> None:
 
 
 def more() -> None:
-
     @text_demo('Clearable', '''
         The `clearable` prop from [Quasar](https://quasar.dev/) adds a button to the input that clears the text.    
     ''')
     def clearable():
         i = ui.number(value=42).props('clearable')
         ui.label().bind_text_from(i, 'value')
+
+    @text_demo('Number of decimal places', '''
+        You can specify the number of decimal places using the `precision` parameter.
+        A negative value means decimal places before the dot.
+        The rounding takes place when the input loses focus,
+        when sanitization parameters like min, max or precision change,
+        or when `sanitize()` is called manually.
+    ''')
+    def integer():
+        n = ui.number(value=3.14159265359, precision=5)
+        n.sanitize()