Bläddra i källkod

Handle multi-select (#1082)

Nikhil Rao 2 år sedan
förälder
incheckning
9485127c1c

+ 14 - 0
pynecone/components/component.py

@@ -104,6 +104,11 @@ class Component(Base, ABC):
         initial_kwargs = {
             "id": kwargs.get("id"),
             "children": kwargs.get("children", []),
+            **{
+                prop: Var.create(kwargs[prop])
+                for prop in self.get_initial_props()
+                if prop in kwargs
+            },
         }
         super().__init__(**initial_kwargs)
 
@@ -343,6 +348,15 @@ class Component(Base, ABC):
         """
         return set(cls.get_fields()) - set(Component.get_fields())
 
+    @classmethod
+    def get_initial_props(cls) -> Set[str]:
+        """Get the initial props to set for the component.
+
+        Returns:
+            The initial props to set.
+        """
+        return set()
+
     @classmethod
     def create(cls, *children, **props) -> Component:
         """Create the component.

+ 17 - 4
pynecone/components/forms/select.py

@@ -1,6 +1,6 @@
 """Provides a feature-rich Select and some (not all) related components."""
 
-from typing import Any, Dict, List, Optional, Union
+from typing import Any, Dict, List, Optional, Set, Union
 
 from pynecone.base import Base
 from pynecone.components.component import Component
@@ -304,9 +304,22 @@ class Select(Component):
         Returns:
             A dict mapping the event trigger to the var that is passed to the handler.
         """
-        return {
-            "on_change": EVENT_ARG.value,
-        }
+        # A normal select returns the value.
+        value = EVENT_ARG.value
+
+        # Multi-select returns a list of values.
+        if self.is_multi:
+            value = Var.create_safe(f"{EVENT_ARG}.map(e => e.value)", is_local=True)
+        return {"on_change": value}
+
+    @classmethod
+    def get_initial_props(cls) -> Set[str]:
+        """Get the initial props to set for the component.
+
+        Returns:
+            The initial props to set.
+        """
+        return super().get_initial_props() | {"is_multi"}
 
     @classmethod
     def create(

+ 1 - 1
pyproject.toml

@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "pynecone"
-version = "0.1.31"
+version = "0.1.32"
 description = "Web apps in pure Python."
 license = "Apache-2.0"
 authors = [

+ 7 - 7
tests/components/forms/test_uploads.py

@@ -47,18 +47,18 @@ def test_upload_component_render(upload_component):
     Args:
         upload_component: component fixture
     """
-    uplaod = upload_component.render()
+    upload = upload_component.render()
 
     # upload
-    assert uplaod["name"] == "ReactDropzone"
-    assert uplaod["props"] == [
+    assert upload["name"] == "ReactDropzone"
+    assert upload["props"] == [
         "multiple={true}",
         "onDrop={e => File(e)}",
     ]
-    assert uplaod["args"] == ("getRootProps", "getInputProps")
+    assert upload["args"] == ("getRootProps", "getInputProps")
 
     # box inside of upload
-    [box] = uplaod["children"]
+    [box] = upload["children"]
     assert box["name"] == "Box"
     assert box["props"] == [
         'sx={{"border": "1px dotted black"}}',
@@ -86,9 +86,9 @@ def test_upload_component_with_props_render(upload_component_with_props):
     Args:
         upload_component_with_props: component fixture
     """
-    uplaod = upload_component_with_props.render()
+    upload = upload_component_with_props.render()
 
-    assert uplaod["props"] == [
+    assert upload["props"] == [
         "maxFiles={2}",
         "multiple={true}",
         "noDrag={true}",